getInputTypes() {
- return TransformManager.CONTENT_CLASS
- }
-
- /**
- * 指Transform要操作内容的范围,官方文档Scope有7种类型:
- *
- * EXTERNAL_LIBRARIES 只有外部库
- * PROJECT 只有项目内容
- * PROJECT_LOCAL_DEPS 只有项目的本地依赖(本地jar)
- * PROVIDED_ONLY 只提供本地或远程依赖项
- * SUB_PROJECTS 只有子项目。
- * SUB_PROJECTS_LOCAL_DEPS 只有子项目的本地依赖项(本地jar)。
- * TESTED_CODE 由当前变量(包括依赖项)测试的代码
- * SCOPE_FULL_PROJECT 整个项目
- */
- @Override
- public Set super QualifiedContent.Scope> getScopes() {
- return TransformManager.SCOPE_FULL_PROJECT
- }
-
- @Override
- public boolean isIncremental() {
- return false;
- }
-
- @Override
- void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
- transformInvocation.inputs.each { TransformInput input ->
- input.directoryInputs.each { DirectoryInput directoryInput ->
- if (directoryInput.file.isDirectory()) {
- directoryInput.file.eachFileRecurse { File file ->
- tranformFile(file)
- }
- } else {
- tranformFile(file)
- }
- // Transform 拷贝文件到 transforms 目录
- File dest = transformInvocation.outputProvider.getContentLocation(
- directoryInput.getName(),
- directoryInput.getContentTypes(),
- directoryInput.getScopes(),
- Format.DIRECTORY);
- // 将修改过的字节码copy到dest,实现编译期间干预字节码
- FileUtils.copyDirectory(directoryInput.getFile(), dest);
- }
-
- input.jarInputs.each { JarInput jarInput ->
- def jarName = jarInput.name
- def dest = transformInvocation.outputProvider.getContentLocation(jarName,
- jarInput.contentTypes, jarInput.scopes, Format.JAR)
-
- FileUtils.copyFile(jarInput.getFile(), dest)
- }
- }
-
- }
-
- // 处理响应的文件
- private void tranformFile(File file) throws IOException {
- def name = file.name
- //println file.getAbsolutePath()
- if (filerClass(name)) {
- //println file.getAbsolutePath()
- ClassReader reader = new ClassReader(file.bytes)
- ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS)
- ClassVisitor visitor = new TimePluginClassVisitor(writer)
- reader.accept(visitor, ClassReader.EXPAND_FRAMES)
-
- byte[] code = writer.toByteArray()
- def classPath = file.parentFile.absolutePath + File.separator + name
- println classPath
- FileOutputStream fos = new FileOutputStream(classPath)
- fos.write(code)
- fos.close()
- }
- }
-
- private boolean filerClass(String name) {
- //return name.endsWith("Activity.class")
- return name.endsWith("Fragment.class")
- }
-}
diff --git a/android/AndroidProject/buildSrc/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties b/android/AndroidProject/buildSrc/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties
deleted file mode 100644
index b753dae4..00000000
--- a/android/AndroidProject/buildSrc/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties
+++ /dev/null
@@ -1 +0,0 @@
-implementation-class=com.immoc.router.gradle.RouterPlugin
\ No newline at end of file
diff --git a/android/AndroidProject/gradle.properties b/android/AndroidProject/gradle.properties
deleted file mode 100644
index 98bed167..00000000
--- a/android/AndroidProject/gradle.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
-# AndroidX package structure to make it clearer which packages are bundled with the
-# Android operating system, and which are packaged with your app"s APK
-# https://developer.android.com/topic/libraries/support-library/androidx-rn
-android.useAndroidX=true
-# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
-# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
\ No newline at end of file
diff --git a/android/AndroidProject/gradle/wrapper/gradle-wrapper.jar b/android/AndroidProject/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index e708b1c0..00000000
Binary files a/android/AndroidProject/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/android/AndroidProject/gradle/wrapper/gradle-wrapper.properties b/android/AndroidProject/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index d35656ea..00000000
--- a/android/AndroidProject/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Fri Aug 20 10:57:32 CST 2021
-distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
-distributionPath=wrapper/dists
-zipStorePath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
diff --git a/android/AndroidProject/gradlew b/android/AndroidProject/gradlew
deleted file mode 100755
index 4f906e0c..00000000
--- a/android/AndroidProject/gradlew
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2015 the original author or authors.
-#
-# 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
-#
-# https://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.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-exec "$JAVACMD" "$@"
diff --git a/android/AndroidProject/gradlew.bat b/android/AndroidProject/gradlew.bat
deleted file mode 100644
index 107acd32..00000000
--- a/android/AndroidProject/gradlew.bat
+++ /dev/null
@@ -1,89 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/android/AndroidProject/kotlinLib/.gitignore b/android/AndroidProject/kotlinLib/.gitignore
deleted file mode 100644
index 42afabfd..00000000
--- a/android/AndroidProject/kotlinLib/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android/AndroidProject/kotlinLib/build.gradle b/android/AndroidProject/kotlinLib/build.gradle
deleted file mode 100644
index 2bed8f12..00000000
--- a/android/AndroidProject/kotlinLib/build.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-plugins {
- id 'java-library'
- id 'kotlin'
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
-}
\ No newline at end of file
diff --git a/android/AndroidProject/kotlinLib/src/main/java/com/joyy/kotlinlib/MyClass.kt b/android/AndroidProject/kotlinLib/src/main/java/com/joyy/kotlinlib/MyClass.kt
deleted file mode 100644
index 65020bce..00000000
--- a/android/AndroidProject/kotlinLib/src/main/java/com/joyy/kotlinlib/MyClass.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.joyy.kotlinlib
-
-class Command(val name: Any, val invokeMethod: (() -> Unit)) {
- override fun toString(): String {
- return "Command(name=$name, invokeMethod=$invokeMethod)"
- }
-}
-
-class MyClass {
-
- // val list = ArrayList()
- val hashMap = hashMapOf String?>()
-
-
- fun add() {
-// list.add(Command("test_one") { println("test_one") })
-// list.add(Command("test_two") { println("test_two") })
-// list.add(Command("test_three") { println("test_three") })
- val key_0 = "test_one"
- val key_1 = "test_two"
- val key_2 = "test_thr"
-
-
- hashMap[key_0] = { "test_0" }
- hashMap[key_1] = { "test_1" }
- hashMap[key_2] = { "test_2" }
- }
-
- fun invoke() {
- hashMap.forEach { (k, v) ->
- //println("k = $k , v = $v")
- println(v())
- }
-// for (func in list) {
-// println(func)
-// func.invokeMethod()
-// }
- }
-
- // 1. JS调用
- // 2。JS调用取回值
- // 3。JAVA调用 X
- // 4。 JAVA调用取回值 X
-}
-
-fun main() {
- println("Hello World")
- // 想干什么
- // 1. List方法
- // 2。 打印方法名称
- // 3。调用方法
- val my = MyClass()
- my.add()
- my.invoke()
-}
\ No newline at end of file
diff --git a/android/AndroidProject/maven-publish.gradle b/android/AndroidProject/maven-publish.gradle
deleted file mode 100644
index f8c53a24..00000000
--- a/android/AndroidProject/maven-publish.gradle
+++ /dev/null
@@ -1,43 +0,0 @@
-apply plugin: 'maven'
-
-//读取工程的配置
-Properties gradleProperties = new Properties()
-gradleProperties.load(project.rootProject.file("gradle.properties").newDataInputStream())
-def VERSION_NAME = gradleProperties.getProperty("VERSION_NAME")
-def POM_URL = gradleProperties.getProperty("POM_URL")
-def GROUP_ID = gradleProperties.getProperty("GROUP_ID")
-
-Properties projectGradleProperties = new Properties()
-projectGradleProperties.load(
- project.file('gradle.properties').newDataInputStream()
-)
-def POM_ARTIFACT_ID = projectGradleProperties.getProperty("POM_ARTIFACT_ID")
-
-println("maven-publish VERSION_NAME=$VERSION_NAME")
-println("maven-publish POM_URL=$POM_URL")
-println("maven-publish POM_URL=$POM_URL")
-println("maven-publish GROUP_ID=$GROUP_ID")
-
-
-//发布任务
-uploadArchives {
- repositories {
- mavenDeployer {
- // 填入发布信息
- repository(url: uri(POM_URL)) {
- pom.groupId = GROUP_ID
- pom.artifactId = POM_ARTIFACT_ID
- pom.version = VERSION_NAME
- }
- pom.whenConfigured { pom ->
- pom.dependencies.forEach { dep ->
- if(dep.getVersion() == "unspecified") {
- dep.setGroupId(GROUP_ID)
- dep.setVersion(VERSION_NAME)
- }
- }
- }
-
- }
- }
-}
diff --git a/android/AndroidProject/router-annotations/.gitignore b/android/AndroidProject/router-annotations/.gitignore
deleted file mode 100644
index 42afabfd..00000000
--- a/android/AndroidProject/router-annotations/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android/AndroidProject/router-annotations/build.gradle b/android/AndroidProject/router-annotations/build.gradle
deleted file mode 100644
index 72ff6c2e..00000000
--- a/android/AndroidProject/router-annotations/build.gradle
+++ /dev/null
@@ -1,12 +0,0 @@
-// 应用java插件
-apply plugin: 'java'
-
-// 设置源码兼容性
-targetCompatibility = JavaVersion.VERSION_1_7
-sourceCompatibility = JavaVersion.VERSION_1_7
-
-
-// 应用发布功能
-//apply from : rootProject.file("maven-publish.gradle")
-
-
diff --git a/android/AndroidProject/router-annotations/gradle.properties b/android/AndroidProject/router-annotations/gradle.properties
deleted file mode 100644
index 3abb442e..00000000
--- a/android/AndroidProject/router-annotations/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-POM_ARTIFACT_ID=router-annotations
\ No newline at end of file
diff --git a/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Destination.java b/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Destination.java
deleted file mode 100644
index 91f9405a..00000000
--- a/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Destination.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.imooc.router.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Time:2021/7/5 20:14
- * Author:
- * Description: 当前可以修饰的元素,此处标识可以用于标记在类上面
- */
-@Target({ElementType.TYPE}) // 元注解
-@Retention(RetentionPolicy.CLASS)// 能被保留到什么时间点
-public @interface Destination {
- String url(); //页面的URL,不能为空
- String description();//页面的描述
-}
diff --git a/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Test.java b/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Test.java
deleted file mode 100644
index dfdc2745..00000000
--- a/android/AndroidProject/router-annotations/src/main/java/com/imooc/router/annotations/Test.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.imooc.router.annotations;
-
-/**
- * Time:2021/7/5 20:20
- * Author:
- * Description:
- */
-public class Test {
-}
diff --git a/android/AndroidProject/router-gradle-plugin/.gitignore b/android/AndroidProject/router-gradle-plugin/.gitignore
deleted file mode 100644
index 7af6eed2..00000000
--- a/android/AndroidProject/router-gradle-plugin/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-/build
-/.settings/
-/bin/main/
-/.classpath
-/.project
diff --git a/android/AndroidProject/router-gradle-plugin/build.gradle b/android/AndroidProject/router-gradle-plugin/build.gradle
deleted file mode 100644
index 15365960..00000000
--- a/android/AndroidProject/router-gradle-plugin/build.gradle
+++ /dev/null
@@ -1,65 +0,0 @@
-apply plugin: 'groovy'
-dependencies {
- implementation gradleApi()
- implementation localGroovy()
- implementation 'com.android.tools.build:gradle:4.2.1'
- implementation 'org.ow2.asm:asm:7.0'
- implementation 'commons-io:commons-io:2.8.0'
-}
-repositories {
-// google()
-// jcenter()
- maven {
- url 'http://repo.duowan.com:8181/nexus/content/groups/public'
- allowInsecureProtocol = true
- }
-}
-
-//cp -rf buildSrc router-gradle-plugin
-//./gradlew :router-gradle-plugin:uploadArchives
-
-//apply plugin: 'maven'
-
-//uploadArchives {
-// repositories {
-// mavenDeployer {
-// // 设置发布路径为 工程根目录下面的repo文件夹
-// repositoriy(url: uri('../repo')) {
-// // 设置groupId,通常为包名
-// pom.groupId = 'com.imooc.router'
-// // 设置artifactId,为当前插件的名称
-// pom.artifactId = 'router-gradle-plugin'
-// // 设置 插件的版本号
-// pom.version = '1.0.0'
-// }
-// }
-// }
-//}
-// 调用maven插件,用于发布
-
-//println("router-gradle-plugin 中的 build.gradle")
-
-//apply plugin: 'maven'
-
-//// 配置maven插件中的uploadArchives任务
-//uploadArchives {
-// repositories {
-// mavenDeployer {
-//
-// // 设置发布路径为 工程根目录下面的 repo 文件夹
-// repository(url: uri('../repo')) {
-//
-// // 设置groupId,通常为包名
-// pom.groupId = 'com.immoc.router'
-//
-// // 设置artifactId,为当前插件的名称
-// pom.artifactId = 'router-gradle-plugin'
-//
-// // 设置 插件的版本号
-// pom.version = '1.0.1'
-//
-// }
-//
-// }
-// }
-//}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/ClassAdapterVisitor.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/ClassAdapterVisitor.groovy
deleted file mode 100644
index d971c3ac..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/ClassAdapterVisitor.groovy
+++ /dev/null
@@ -1,18 +0,0 @@
-import jdk.internal.org.objectweb.asm.Opcodes
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.MethodVisitor
-import joyy.CustomMethodVisitor
-
-public class ClassAdapterVisitor extends ClassVisitor {
- public ClassAdapterVisitor(ClassVisitor api) {
- super(Opcodes.ASM6, api);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
- System.err.println("方法名称:" + name + " signature:" + signature + " descriptor=" + descriptor);
- //得到MethodVistor 然后传递给使用自定义的包装类来返回
- MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
- return new CustomMethodVisitor(api, mv, access, name, descriptor);
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/CustomMethodVisitor.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/CustomMethodVisitor.groovy
deleted file mode 100644
index b91d29df..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/CustomMethodVisitor.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-package joyy;
-
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.commons.AdviceAdapter;
-import org.objectweb.asm.commons.Method;
-
-public class CustomMethodVisitor extends AdviceAdapter {
-
- protected CustomMethodVisitor(int api, MethodVisitor methodVisitor, int access, String name, String descriptor) {
- super(api, methodVisitor, access, name, descriptor);
- }
-
- private int start;
-
- /**
- * 方法进入的时候执行
- */
- @Override
- protected void onMethodEnter() {
- super.onMethodEnter();
- //invokeStatic指令,调用静态方法
- invokeStatic(Type.getType("Ljava/lang/System;"),
- new Method("currentTimeMillis", "()J"));
- //创建本地 LONG类型变量
- start = newLocal(Type.LONG_TYPE);
- //store指令 将方法执行结果从操作数栈存储到局部变量
- storeLocal(start);
- }
-
- /**
- * 方法返回的时候执行
- * @param opcode
- */
- @Override
- protected void onMethodExit(int opcode) {
- super.onMethodExit(opcode);
- invokeStatic(Type.getType("Ljava/lang/System;"), new Method("currentTimeMillis", "()J"));
- int end = newLocal(Type.LONG_TYPE);
- //store指令 将方法执行结果从操作数栈存储到局部变量
- storeLocal(end);
-
- getStatic(Type.getType("Ljava/lang/System;"),"out",Type.getType( "Ljava/io/PrintStream;"));
- newInstance(Type.getType("Ljava/lang/StringBuilder;"));
- dup();
- invokeConstructor(Type.getType("Ljava/lang/StringBuilder;"), new Method("", "()V"));
- visitLdcInsn("execute :");
- invokeVirtual(Type.getType("Ljava/lang/StringBuilder;"),new Method("append","(Ljava/lang/String;)Ljava/lang/StringBuilder;"));
- loadLocal(end);
- loadLocal(start);
- math(SUB,Type.LONG_TYPE);
- invokeVirtual(Type.getType("Ljava/lang/StringBuilder;"),new Method("append", "(J)Ljava/lang/StringBuilder;"));
- visitLdcInsn("ms.");
- invokeVirtual(Type.getType("Ljava/lang/StringBuilder;"),new Method("append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;"));
- invokeVirtual(Type.getType("Ljava/lang/StringBuilder;"),new Method("toString", "()Ljava/lang/String;"));
- invokeVirtual(Type.getType("Ljava/io/PrintStream;"),new Method("println", "(Ljava/lang/String;)V"));
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyPlugin.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyPlugin.groovy
deleted file mode 100644
index edd484cd..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyPlugin.groovy
+++ /dev/null
@@ -1,15 +0,0 @@
-package joyy
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-
-class MyPlugin implements Plugin {
-
- @Override
- void apply(Project target) {
- println "MyPlugin apply(Project)"
- //target.android.registerTransform(new MyTransform(target))
- target.android.registerTransform(new TimePluginTransform())
-
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyTransform.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyTransform.groovy
deleted file mode 100644
index b28418d0..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/MyTransform.groovy
+++ /dev/null
@@ -1,175 +0,0 @@
-package joyy
-
-import com.android.build.api.transform.*
-import com.android.build.gradle.internal.pipeline.TransformManager
-import groovy.io.FileType
-import org.gradle.api.Project
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassWriter
-import org.objectweb.asm.tree.ClassNode
-import org.objectweb.asm.tree.MethodNode
-
-class MyTransform extends Transform {
-
- Project project;
-
- MyTransform(Project project) {
- this.project = project
- }
-
- @Override
- String getName() {
- return "joyy.MyTransform"
- }
-
- @Override
- Set getInputTypes() {
- return TransformManager.CONTENT_CLASS
- }
-
- @Override
- Set super QualifiedContent.Scope> getScopes() {
- return TransformManager.SCOPE_FULL_PROJECT
- }
-
- @Override
- boolean isIncremental() {
- return true //通常返回false
- }
-
- @Override
- void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
- //super.transform(transformInvocation)
- println "joyy.MyTransform transform() start"
- def start = System.currentTimeMillis()
-
- transformInvocation.getInputs().forEach({ input ->
- input.directoryInputs.forEach({ dir ->
- handleDirectoryInputs(dir, transformInvocation)
- })
- })
-
-// transformInvocation.getInputs().forEach(input -> {
-// input.getDirectoryInputs().forEach(dir -> {
-// handleDirectoryInputs(dir, transformInvocation);
-// })
-// });
-
-
- def end = System.currentTimeMillis();
- println "joyy.MyTransform transform() end total = ${end - start}"
- }
-
- private boolean checkFileName(String name) {
- return name != null && name.endsWith("Fragment.class")
- }
-
- /**
- * handle Directory
- */
- private void handleDirectoryInputs(DirectoryInput dir, TransformInvocation transformInvocation) {
- try {
- if (dir.getFile().isDirectory()) {
-// transformDir(dir.getFile());
- System.out.println("fragment_build #### handleDirectoryInputs " + dir.getFile().getName());
- File dest = transformInvocation.getOutputProvider().getContentLocation(dir.getName(),
- dir.getContentTypes(), dir.getScopes(),
- Format.DIRECTORY);
-
- if (dir.file) {
- def modifiedRecord = [:]
- dir.file.traverse(type: FileType.FILES, nameFilter: ~/.*\.class/) { File classFile ->
- def className = classFile.absolutePath
- if (checkFileName(className)) {
- println "className = $className" // 得到Class
-
- FileInputStream fis = new FileInputStream(className);
- ClassReader cr = new ClassReader(fis)
- /*** 2、执行分析与插桩*/
- //class字节码的读取与分析引擎
- // 写出器 COMPUTE_FRAMES 自动计算所有的内容,后续操作更简单
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-
- // 分析,处理结果写入cw EXPAND_FRAMES:栈图以扩展格式进行访问
- cr.accept(new ClassAdapterVisitor(cw), ClassReader.EXPAND_FRAMES)
- /** 3、获得结果并输出*/
- byte[] newClassBytes = cw.toByteArray()
- FileOutputStream fos = FileOutputStream("/Users/flannery/Desktop/AndroidHelper/buildSrc/a.class");
- fos.write(newClassBytes)
- fis.close()
- fos.close()
- }
-// if (!ASMHelper.filter(className)) {
-// def transformedClass = ASMHelper.transformClass(classFile, dir.file, transformInvocation.context.temporaryDir)
-// modifiedRecord[(className)] = transformedClass
-// }
- }
-// FileUtils.copyDirectory(dir.file, destDir)
-// modifiedRecord.each { name, file ->
-// def targetFile = new File(destDir.absolutePath, name)
-// if (targetFile.exists()) {
-// targetFile.delete()
-// }
-// FileUtils.copyFile(file, targetFile)
-// }
-// modifiedRecord.clear()
- }
-// try {
-// FileUtils.copyDirectory(dir.getFile(), dest);
-// } catch (IOException e) {
-// e.printStackTrace();
-// }
- }
- } catch(Exception e) {
- e.printStackTrace()
- }
- }
-
- byte[] modifyClass(InputStream inputStream) {
- ClassNode classNode = new ClassNode(Opcodes.ASM5)
- ClassReader classReader = new ClassReader(inputStream)
- // 1. 将读入的字节转换为ClassNode
- classReader.accept(classNode, 0)
- // 2. 对classNode的处理逻辑
- Iterator iterator = classNode.methods.iterator()
- while(iterator.hasNext()) {
- MethodNode node = iterator.next()
- if(node.name.startsWith("test")) {
- iterator.remove()
- }
- }
- ClassWriter classWriter = new ClassWriter(0)
- // 3 将classNode转为字节数组
- classNode.accept(classWriter)
- return classWriter.toByteArray()
- }
-
- // 是否是Class文件
-// private boolean checkClassFile(String name) {
-// return (name.endsWith(".class")
-// && !name.startsWith("R\\$")
-// && !"R.class".equals(name)
-// && !"BuildConfig.class".equals(name)
-// && checkScanFile(name));
-// }
-
-
- //android.telephony.TelephonyManager,getLine1Number
- //android.telephony.TelephonyManager,getDeviceId
- //android.telephony.TelephonyManager,getSubscriberId
-
- //com.zipow.videobox.sip.server.CmmSIPCallManager.class
- //com/zipow/videobox/fragment/c.class
- //com/huawei/hms/update/f/a.class
-// private boolean checkScanFile(String name) {
-// int size1 = classesList.size();
-// for (int i = 0; i < size1; i++) {
-// if (classesList.get(i).equals(name)) {
-// return true;
-// }
-// }
-// return false
-// }
-
-
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimeMethodVisitor.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimeMethodVisitor.groovy
deleted file mode 100644
index 4813af06..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimeMethodVisitor.groovy
+++ /dev/null
@@ -1,52 +0,0 @@
-package joyy
-
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.AnnotationVisitor
-import org.objectweb.asm.MethodVisitor
-
-public class TimeMethodVisitor extends MethodVisitor {
-
- private String className
-
- private String methodName
-
- private boolean isInject // 是否为注解方法
-
- public TimeMethodVisitor(MethodVisitor methodVisitor, String className, String methodName) {
- super(Opcodes.ASM5, methodVisitor)
- this.className = className
- this.methodName = methodName
- }
-
- @Override
- AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (desc.contains("InjectTimestamp")) {
- isInject = true
- }
- return super.visitAnnotation(desc, visible)
- }
-
- @Override
- void visitCode() {
-
- if (isInject) {
- mv.visitLdcInsn(className + " -> TAG");
- mv.visitLdcInsn("开始时间:" + System.currentTimeMillis());
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "android/util/Log", "e", "(Ljava/lang/String;Ljava/lang/String;)I", false);
- mv.visitInsn(Opcodes.POP);
- }
- super.visitCode()
- }
-
- @Override
- void visitInsn(int opcode) {
-
- if (isInject && opcode == Opcodes.RETURN) {
- mv.visitLdcInsn(className + " -> TAG");
- mv.visitLdcInsn("结束时间:" + System.currentTimeMillis());
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "android/util/Log", "e", "(Ljava/lang/String;Ljava/lang/String;)I", false);
- mv.visitInsn(Opcodes.POP);
- }
- super.visitInsn(opcode)
- }
-}
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePlugin.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePlugin.groovy
deleted file mode 100644
index 5d26a3d0..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePlugin.groovy
+++ /dev/null
@@ -1,17 +0,0 @@
-
-package joyy
-
-import com.android.build.gradle.AppExtension
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-
-public class TimePlugin implements Plugin {
-
- @Override
- void apply(Project project) {
- println ("TimePlugin load sucess")
- AppExtension appExtension = project.getExtensions().getByType(AppExtension.class)
- appExtension.registerTransform(new TimePluginTransform())
-
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginClassVisitor.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginClassVisitor.groovy
deleted file mode 100644
index eaf92634..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginClassVisitor.groovy
+++ /dev/null
@@ -1,30 +0,0 @@
-package joyy
-
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes;
-
-public class TimePluginClassVisitor extends ClassVisitor {
-
- private String className
- TimePluginClassVisitor(ClassVisitor cv) {
- super(Opcodes.ASM5, cv)
- }
-
- @Override
- void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- super.visit(version, access, name, signature, superName, interfaces)
- this.className = name
- }
-
- @Override
- MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- MethodVisitor mv = cv.visitMethod(access,name,desc,signature,exceptions)
- return new TimeMethodVisitor(mv, className, name)
- }
-
- @Override
- void visitEnd() {
- super.visitEnd()
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginTransform.groovy b/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginTransform.groovy
deleted file mode 100644
index 32804f97..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/groovy/joyy/TimePluginTransform.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-package joyy;
-
-import com.android.build.api.transform.*;
-import com.android.build.gradle.internal.pipeline.TransformManager
-import com.android.utils.FileUtils
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassWriter;
-
-class TimePluginTransform extends Transform {
- @Override
- public String getName() {
- return TimePluginTransform.class.getSimpleName()
- }
-
- @Override
- public Set getInputTypes() {
- return TransformManager.CONTENT_CLASS
- }
-
- /**
- * 指Transform要操作内容的范围,官方文档Scope有7种类型:
- *
- * EXTERNAL_LIBRARIES 只有外部库
- * PROJECT 只有项目内容
- * PROJECT_LOCAL_DEPS 只有项目的本地依赖(本地jar)
- * PROVIDED_ONLY 只提供本地或远程依赖项
- * SUB_PROJECTS 只有子项目。
- * SUB_PROJECTS_LOCAL_DEPS 只有子项目的本地依赖项(本地jar)。
- * TESTED_CODE 由当前变量(包括依赖项)测试的代码
- * SCOPE_FULL_PROJECT 整个项目
- */
- @Override
- public Set super QualifiedContent.Scope> getScopes() {
- return TransformManager.SCOPE_FULL_PROJECT
- }
-
- @Override
- public boolean isIncremental() {
- return false;
- }
-
- @Override
- void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
- transformInvocation.inputs.each { TransformInput input ->
- input.directoryInputs.each { DirectoryInput directoryInput ->
- if (directoryInput.file.isDirectory()) {
- directoryInput.file.eachFileRecurse { File file ->
- tranformFile(file)
- }
- } else {
- tranformFile(file)
- }
- // Transform 拷贝文件到 transforms 目录
- File dest = transformInvocation.outputProvider.getContentLocation(
- directoryInput.getName(),
- directoryInput.getContentTypes(),
- directoryInput.getScopes(),
- Format.DIRECTORY);
- // 将修改过的字节码copy到dest,实现编译期间干预字节码
- FileUtils.copyDirectory(directoryInput.getFile(), dest);
- }
-
- input.jarInputs.each { JarInput jarInput ->
- def jarName = jarInput.name
- def dest = transformInvocation.outputProvider.getContentLocation(jarName,
- jarInput.contentTypes, jarInput.scopes, Format.JAR)
-
- FileUtils.copyFile(jarInput.getFile(), dest)
- }
- }
-
- }
-
- // 处理响应的文件
- private void tranformFile(File file) throws IOException {
- def name = file.name
- //println file.getAbsolutePath()
- if (filerClass(name)) {
- //println file.getAbsolutePath()
- ClassReader reader = new ClassReader(file.bytes)
- ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS)
- ClassVisitor visitor = new TimePluginClassVisitor(writer)
- reader.accept(visitor, ClassReader.EXPAND_FRAMES)
-
- byte[] code = writer.toByteArray()
- def classPath = file.parentFile.absolutePath + File.separator + name
- println classPath
- FileOutputStream fos = new FileOutputStream(classPath)
- fos.write(code)
- fos.close()
- }
- }
-
- private boolean filerClass(String name) {
- //return name.endsWith("Activity.class")
- return name.endsWith("Fragment.class")
- }
-}
diff --git a/android/AndroidProject/router-gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties b/android/AndroidProject/router-gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties
deleted file mode 100644
index b753dae4..00000000
--- a/android/AndroidProject/router-gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.immoc.router.properties
+++ /dev/null
@@ -1 +0,0 @@
-implementation-class=com.immoc.router.gradle.RouterPlugin
\ No newline at end of file
diff --git a/android/AndroidProject/router-processor/.gitignore b/android/AndroidProject/router-processor/.gitignore
deleted file mode 100644
index 42afabfd..00000000
--- a/android/AndroidProject/router-processor/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android/AndroidProject/router-processor/build.gradle b/android/AndroidProject/router-processor/build.gradle
deleted file mode 100644
index ab184e0e..00000000
--- a/android/AndroidProject/router-processor/build.gradle
+++ /dev/null
@@ -1,15 +0,0 @@
-apply plugin: 'java'
-
-dependencies {
- implementation project(':router-annotations')
- implementation 'com.google.auto.service:auto-service:1.0-rc6'
- annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
- implementation 'com.google.code.gson:gson:2.8.7'
-}
-
-// 应用发布功能
-//apply from : rootProject.file("maven-publish.gradle")
-java {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-}
\ No newline at end of file
diff --git a/android/AndroidProject/router-processor/gradle.properties b/android/AndroidProject/router-processor/gradle.properties
deleted file mode 100644
index 162eee47..00000000
--- a/android/AndroidProject/router-processor/gradle.properties
+++ /dev/null
@@ -1 +0,0 @@
-POM_ARTIFACT_ID=router-processor
\ No newline at end of file
diff --git a/android/AndroidProject/router-processor/src/main/java/com/imooc/router/processor/DestinationProcessor.java b/android/AndroidProject/router-processor/src/main/java/com/imooc/router/processor/DestinationProcessor.java
deleted file mode 100644
index f634ac54..00000000
--- a/android/AndroidProject/router-processor/src/main/java/com/imooc/router/processor/DestinationProcessor.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package com.imooc.router.processor;
-
-import com.google.auto.service.AutoService;
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import com.imooc.router.annotations.Destination;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.Set;
-
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardLocation;
-
-/**
- * Time:2021/7/5 20:42
- * Author:
- * Description:
- */
-@AutoService(Processor.class)
-public class DestinationProcessor extends AbstractProcessor {
-
-
- @Override
- public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.RELEASE_8;
- }
-
- private static final String TAG = "DestinationProcessor";
-
- /**
- * 告诉编译器,当前处理器支持的注解类型
- *
- * @return
- */
- @Override
- public Set getSupportedAnnotationTypes() {
- return Collections.singleton(
- Destination.class.getCanonicalName()
- );
- }
-
-
- /**
- * 编译器找到我们关心的注解后,会回调这个方法
- *
- * @param annotations
- * @param roundEnv
- * @return
- */
- @Override
- public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
-
- // 避免多次调用process
- if (roundEnv.processingOver()) {
- return false;
- }
-
-
- System.out.println(TAG + " >>> process start ... ");
-
- // 传递过来的参数
- String rootDir = processingEnv.getOptions().get("root_project_dir");
- if (rootDir == null) {
- return false;
-// throw new RuntimeException("rootDir = " + rootDir); // 编译过程比较漫长,这么比较快的退出
- }
-
-
- // 获取所有标记了@Destination注解的类的信息
- Set extends Element> allDestinationElements = roundEnv.getElementsAnnotatedWith(Destination.class);
- System.out.println(TAG + " >>> all Destination Element count = " + allDestinationElements.size());
- // 当未收集到@Destination注解的时候,跳过后续流程
- if (allDestinationElements.size() < 1) {
- return false;
- }
- final String packName = "com.example.routerdemo";
- String className = "RouterMapping_" + System.currentTimeMillis();
- StringBuilder builder = new StringBuilder();
- builder.append("package ").append(packName).append(";\n\n");
- builder.append("import java.util.HashMap;").append("\n");
- builder.append("import java.util.Map;").append("\n");
- builder.append("public class ").append(className).append(" {").append("\n");
- builder.append(" public static Map get() {").append("\n");
- builder.append(" Map mapping = new HashMap<>();").append("\n");
-
- final JsonArray destinationJsonArray = new JsonArray();
-
- // 遍历所有注解信息, 挨个获取详细信息
- for (Element element : allDestinationElements) {
- final TypeElement typeElement = (TypeElement) element;
- // 尝试在当前类上获取@Destination的信息
- final Destination destination = typeElement.getAnnotation(Destination.class);
- if (destination == null) {
- continue;
- }
- final String url = destination.url();
- final String description = destination.description();
- final String realPath = typeElement.getQualifiedName().toString();
- System.out.println(TAG + ">>> url = " + url);
- System.out.println(TAG + ">>> description = " + description);
- System.out.println(TAG + ">>> realPath = " + realPath);
-
- builder.append(" ").append("mapping.put(")
- .append("\"").append(url).append("\"").append(",")
- .append("\"").append(realPath).append("\"")
- .append(");").append("\n");
-
- JsonObject item = new JsonObject();
- item.addProperty("url", url);
- item.addProperty("description", description);
- item.addProperty("realPath", realPath);
- destinationJsonArray.add(item);
- }
- builder.append(" return mapping;").append("\n");
- builder.append(" }").append("\n"); // get()
- builder.append("}").append("\n"); // class
-
- String mappingFullClassName = packName + "." + className;
- System.out.println(mappingFullClassName);
- System.out.println(builder.toString());
-
- //写入自动生成的类到文件中
- try {
- JavaFileObject source = processingEnv.getFiler()
- .createSourceFile(mappingFullClassName);
- Writer writer = source.openWriter();
- writer.write(builder.toString());
- writer.flush();
- writer.close();
- } catch (Exception e) {
- throw new RuntimeException("Error while create file", e);
- }
-
- // 想创建一个资源文件
-// try {
-// System.out.println("[[[创建一个资源文件]]]");
-// System.out.println(processingEnv.getLocale().getCountry());
-// JavaFileObject source = processingEnv.getFiler().createSourceFile("kkkkk.string");
-// } catch (IOException e) {
-// e.printStackTrace();
-// }
-
- System.out.println(rootDir);
- // 写入JSON到本地文件中
- File rootDirFile = new File(rootDir);
- if (!rootDirFile.exists()) throw new RuntimeException("root_project_dir not exits");
- // 创建router_mapping子目录
- File routerFileDir = new File(rootDirFile, "router_mapping");
- if (!routerFileDir.exists()) routerFileDir.mkdirs();
- File mappingFile = new File(routerFileDir, "mapping_" + System.currentTimeMillis() + ".json");
-
- // 写入json的内容
- try {
- BufferedWriter out = new BufferedWriter(new FileWriter(mappingFile));
- String jsonStr = destinationJsonArray.toString();
- out.write(jsonStr);
- out.flush();
- out.close();
- } catch (Exception e) {
- throw new RuntimeException("Error while writing json ", e);
- }
-
- return false;
- }
-}
diff --git a/android/AndroidProject/routerdemo/.gitignore b/android/AndroidProject/routerdemo/.gitignore
deleted file mode 100644
index 42afabfd..00000000
--- a/android/AndroidProject/routerdemo/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/build.gradle b/android/AndroidProject/routerdemo/build.gradle
deleted file mode 100644
index c5b674a0..00000000
--- a/android/AndroidProject/routerdemo/build.gradle
+++ /dev/null
@@ -1,56 +0,0 @@
-plugins {
- id 'com.android.application'
- id 'kotlin-android'
- id 'kotlin-android-extensions'
- id 'kotlin-kapt'
-}
-
-android {
- compileSdkVersion 30
- buildToolsVersion "30.0.3"
-
- defaultConfig {
- applicationId "com.example.routerdemo"
- minSdkVersion 16
- targetSdkVersion 30
- versionCode 1
- versionName "1.0"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- kapt {
- arguments {
- arg("root_project_dir", rootProject.projectDir.absolutePath)
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-dependencies {
-
- println("kotlin_version = $kotlin_version")
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.core:core-ktx:1.6.0'
- implementation 'androidx.appcompat:appcompat:1.3.0'
- implementation 'com.google.android.material:material:1.3.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
-
- implementation project(':router-annotations')
-// annotationProcessor project(':router-processor')
- kapt project(':router-processor')
-// implementation "com.immoc.router:router-annotations:1.0.0"
-// kap "com.immoc.router:router-processor:1.0.0"
-}
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/proguard-rules.pro b/android/AndroidProject/routerdemo/proguard-rules.pro
deleted file mode 100644
index 481bb434..00000000
--- a/android/AndroidProject/routerdemo/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/AndroidManifest.xml b/android/AndroidProject/routerdemo/src/main/AndroidManifest.xml
deleted file mode 100644
index 987f6f05..00000000
--- a/android/AndroidProject/routerdemo/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity.kt b/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity.kt
deleted file mode 100644
index 7ce5a85b..00000000
--- a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.example.routerdemo
-
-import androidx.appcompat.app.AppCompatActivity
-import android.os.Bundle
-import com.imooc.router.annotations.Destination
-
-@Destination(
- url = "router://page-home",
- description = "应用主页"
-)
-class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity2.kt b/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity2.kt
deleted file mode 100644
index b281b10c..00000000
--- a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity2.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.example.routerdemo
-
-import androidx.appcompat.app.AppCompatActivity
-import android.os.Bundle
-import com.imooc.router.annotations.Destination
-
-@Destination(
- url = "router://MainActivity2",
- description = "第二个"
-)
-class MainActivity2 : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main2)
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity3.java b/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity3.java
deleted file mode 100644
index f0b9e9fd..00000000
--- a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/MainActivity3.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.example.routerdemo;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import android.os.Bundle;
-
-import com.imooc.router.annotations.Destination;
-
-@Destination(
- url = "router://MainActivity3",
- description = "第三个"
-)
-public class MainActivity3 extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main3);
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/RouterMapping_123.java b/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/RouterMapping_123.java
deleted file mode 100644
index 2fc66c13..00000000
--- a/android/AndroidProject/routerdemo/src/main/java/com/example/routerdemo/RouterMapping_123.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.example.routerdemo;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Time:2021/7/8 19:21
- * Author:
- * Description:
- */
-public class RouterMapping_123 {
-
- public static Map get() {
- Map mapping = new HashMap<>();
-
- mapping.put("router://xxxx", "com.xxx.Activity");
- mapping.put("router://xxxx2", "com.xxx.Activity2");
- mapping.put("router://xxxx3", "com.xxx.Activity3");
-
- return mapping;
- }
-
-}
diff --git a/android/AndroidProject/routerdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/AndroidProject/routerdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 2b068d11..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/drawable/ic_launcher_background.xml b/android/AndroidProject/routerdemo/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 07d5da9c..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main.xml b/android/AndroidProject/routerdemo/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 4fc24441..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main2.xml b/android/AndroidProject/routerdemo/src/main/res/layout/activity_main2.xml
deleted file mode 100644
index ed1b2503..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main2.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main3.xml b/android/AndroidProject/routerdemo/src/main/res/layout/activity_main3.xml
deleted file mode 100644
index 5146a648..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/layout/activity_main3.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index eca70cfe..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index eca70cfe..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index a571e600..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png
deleted file mode 100644
index 61da551c..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index c41dd285..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png
deleted file mode 100644
index db5080a7..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 6dba46da..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
deleted file mode 100644
index da31a871..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 15ac6817..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
deleted file mode 100644
index b216f2d3..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index f25a4197..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
deleted file mode 100644
index e96783cc..00000000
Binary files a/android/AndroidProject/routerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/AndroidProject/routerdemo/src/main/res/values-night/themes.xml b/android/AndroidProject/routerdemo/src/main/res/values-night/themes.xml
deleted file mode 100644
index bda24f08..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/values-night/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/values/colors.xml b/android/AndroidProject/routerdemo/src/main/res/values/colors.xml
deleted file mode 100644
index f8c6127d..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/values/strings.xml b/android/AndroidProject/routerdemo/src/main/res/values/strings.xml
deleted file mode 100644
index 50bcc96b..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- routerdemo
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/main/res/values/themes.xml b/android/AndroidProject/routerdemo/src/main/res/values/themes.xml
deleted file mode 100644
index 39ef7d1e..00000000
--- a/android/AndroidProject/routerdemo/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/android/AndroidProject/routerdemo/src/test/java/com/example/routerdemo/ExampleUnitTest.kt b/android/AndroidProject/routerdemo/src/test/java/com/example/routerdemo/ExampleUnitTest.kt
deleted file mode 100644
index 7e6e1943..00000000
--- a/android/AndroidProject/routerdemo/src/test/java/com/example/routerdemo/ExampleUnitTest.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.example.routerdemo
-
-import org.junit.Test
-
-import org.junit.Assert.*
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-class ExampleUnitTest {
- @Test
- fun addition_isCorrect() {
- assertEquals(4, 2 + 2)
- }
-}
\ No newline at end of file
diff --git a/android/AndroidProject/settings.gradle b/android/AndroidProject/settings.gradle
deleted file mode 100644
index d7bfa525..00000000
--- a/android/AndroidProject/settings.gradle
+++ /dev/null
@@ -1,22 +0,0 @@
-dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
-// jcenter() // Warning: this repository is going to shut down soon
-// maven { url 'http://repo.duowan.com:8181/nexus/content/groups/public' }
-// maven { url uri("${rootProject.getRootDir().absolutePath}/../../../repo") }
- maven {
- url 'http://repo.duowan.com:8181/nexus/content/groups/public'
- allowInsecureProtocol = true
- }
- }
-}
-rootProject.name = "AndroidProject"
-include ':app'
-include 'router-annotations'
-//include 'router-gradle-plugin'
-include 'router-processor'
-include ':stringescape'
-include ':webviews'
-include ':kotlinLib'
diff --git a/android/AndroidProject/stringescape/.gitignore b/android/AndroidProject/stringescape/.gitignore
deleted file mode 100644
index 42afabfd..00000000
--- a/android/AndroidProject/stringescape/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/android/AndroidProject/stringescape/build.gradle b/android/AndroidProject/stringescape/build.gradle
deleted file mode 100644
index 10a23b39..00000000
--- a/android/AndroidProject/stringescape/build.gradle
+++ /dev/null
@@ -1,11 +0,0 @@
-plugins {
- id 'java-library'
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_1_7
- targetCompatibility = JavaVersion.VERSION_1_7
-}
-
-// 应用发布功能
-//apply from : rootProject.file("maven-publish.gradle")
\ No newline at end of file
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ArrayUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ArrayUtils.java
deleted file mode 100644
index 4762581b..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ArrayUtils.java
+++ /dev/null
@@ -1,8684 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.lang.reflect.Array;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-/**
- * Operations on arrays, primitive arrays (like {@code int[]}) and
- * primitive wrapper arrays (like {@code Integer[]}).
- *
- *
This class tries to handle {@code null} input gracefully.
- * An exception will not be thrown for a {@code null}
- * array input. However, an Object array that contains a {@code null}
- * element may throw an exception. Each method documents its behaviour.
- *
- *
#ThreadSafe#
- * @since 2.0
- */
-public class ArrayUtils {
-
- /**
- * An empty immutable {@code Object} array.
- */
- public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
- /**
- * An empty immutable {@code Class} array.
- */
- public static final Class>[] EMPTY_CLASS_ARRAY = new Class[0];
- /**
- * An empty immutable {@code String} array.
- */
- public static final String[] EMPTY_STRING_ARRAY = new String[0];
- /**
- * An empty immutable {@code long} array.
- */
- public static final long[] EMPTY_LONG_ARRAY = new long[0];
- /**
- * An empty immutable {@code Long} array.
- */
- public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
- /**
- * An empty immutable {@code int} array.
- */
- public static final int[] EMPTY_INT_ARRAY = new int[0];
- /**
- * An empty immutable {@code Integer} array.
- */
- public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
- /**
- * An empty immutable {@code short} array.
- */
- public static final short[] EMPTY_SHORT_ARRAY = new short[0];
- /**
- * An empty immutable {@code Short} array.
- */
- public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
- /**
- * An empty immutable {@code byte} array.
- */
- public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
- /**
- * An empty immutable {@code Byte} array.
- */
- public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
- /**
- * An empty immutable {@code double} array.
- */
- public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
- /**
- * An empty immutable {@code Double} array.
- */
- public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
- /**
- * An empty immutable {@code float} array.
- */
- public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
- /**
- * An empty immutable {@code Float} array.
- */
- public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
- /**
- * An empty immutable {@code boolean} array.
- */
- public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
- /**
- * An empty immutable {@code Boolean} array.
- */
- public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
- /**
- * An empty immutable {@code char} array.
- */
- public static final char[] EMPTY_CHAR_ARRAY = new char[0];
- /**
- * An empty immutable {@code Character} array.
- */
- public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
-
- /**
- * The index value when an element is not found in a list or array: {@code -1}.
- * This value is returned by methods in this class and can also be used in comparisons with values returned by
- * various method from {@link java.util.List}.
- */
- public static final int INDEX_NOT_FOUND = -1;
-
- /**
- *
ArrayUtils instances should NOT be constructed in standard programming.
- * Instead, the class should be used as ArrayUtils.clone(new int[] {2}).
- *
- *
This constructor is public to permit tools that require a JavaBean instance
- * to operate.
- */
- public ArrayUtils() {
- super();
- }
-
-
- // NOTE: Cannot use {@code} to enclose text which includes {}, but is OK
-
-
- // Basic methods handling multi-dimensional arrays
- //-----------------------------------------------------------------------
- /**
- *
Outputs an array as a String, treating {@code null} as an empty array.
- *
- *
Multi-dimensional arrays are handled correctly, including
- * multi-dimensional primitive arrays.
- *
- *
The format is that of Java source code, for example {a,b}.
- *
- * @param array the array to get a toString for, may be {@code null}
- * @return a String representation of the array, '{}' if null array input
- */
- public static String toString(final Object array) {
- return toString(array, "{}");
- }
-
- /**
- *
Outputs an array as a String handling {@code null}s.
- *
- *
Multi-dimensional arrays are handled correctly, including
- * multi-dimensional primitive arrays.
- *
- *
The format is that of Java source code, for example {a,b}.
- *
- * @param array the array to get a toString for, may be {@code null}
- * @param stringIfNull the String to return if the array is {@code null}
- * @return a String representation of the array
- */
- public static String toString(final Object array, final String stringIfNull) {
- if (array == null) {
- return stringIfNull;
- }
- return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
- }
-
- /**
- *
Get a hash code for an array handling multi-dimensional arrays correctly.
- *
- *
Multi-dimensional primitive arrays are also handled correctly by this method.
- *
- * @param array the array to get a hash code for, {@code null} returns zero
- * @return a hash code for the array
- */
- public static int hashCode(final Object array) {
- return new HashCodeBuilder().append(array).toHashCode();
- }
-
- /**
- *
Compares two arrays, using equals(), handling multi-dimensional arrays
- * correctly.
- *
- *
Multi-dimensional primitive arrays are also handled correctly by this method.
- *
- * @param array1 the left hand array to compare, may be {@code null}
- * @param array2 the right hand array to compare, may be {@code null}
- * @return {@code true} if the arrays are equal
- * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
- * removed from future releases.
- */
-// @Deprecated
-// public static boolean isEquals(final Object array1, final Object array2) {
-// return new EqualsBuilder().append(array1, array2).isEquals();
-// }
-
- // To map
- //-----------------------------------------------------------------------
- /**
- *
Converts the given array into a {@link Map}. Each element of the array
- * must be either a {@link Map.Entry} or an Array, containing at least two
- * elements, where the first element is used as key and the second as
- * value.
- *
- *
This method can be used to initialize:
- *
- * // Create a Map mapping colors.
- * Map colorMap = ArrayUtils.toMap(new String[][] {
- * {"RED", "#FF0000"},
- * {"GREEN", "#00FF00"},
- * {"BLUE", "#0000FF"}});
- *
- *
- * This method returns {@code null} for a {@code null} input array.
- *
- * @param array an array whose elements are either a {@link Map.Entry} or
- * an Array containing at least two elements, may be {@code null}
- * @return a {@code Map} that was created from the array
- * @throws IllegalArgumentException if one element of this Array is
- * itself an Array containing less then two elements
- * @throws IllegalArgumentException if the array contains elements other
- * than {@link Map.Entry} and an Array
- */
- public static Map toMap(final Object[] array) {
- if (array == null) {
- return null;
- }
- final Map map = new HashMap<>((int) (array.length * 1.5));
- for (int i = 0; i < array.length; i++) {
- final Object object = array[i];
- if (object instanceof Map.Entry, ?>) {
- final Map.Entry,?> entry = (Map.Entry,?>) object;
- map.put(entry.getKey(), entry.getValue());
- } else if (object instanceof Object[]) {
- final Object[] entry = (Object[]) object;
- if (entry.length < 2) {
- throw new IllegalArgumentException("Array element " + i + ", '"
- + object
- + "', has a length less than 2");
- }
- map.put(entry[0], entry[1]);
- } else {
- throw new IllegalArgumentException("Array element " + i + ", '"
- + object
- + "', is neither of type Map.Entry nor an Array");
- }
- }
- return map;
- }
-
- // Generic array
- //-----------------------------------------------------------------------
- /**
- * Create a type-safe generic array.
- *
- *
The Java language does not allow an array to be created from a generic type:
- *
- *
- public static <T> T[] createAnArray(int size) {
- return new T[size]; // compiler error here
- }
- public static <T> T[] createAnArray(int size) {
- return (T[])new Object[size]; // ClassCastException at runtime
- }
- *
- *
- * Therefore new arrays of generic types can be created with this method.
- * For example, an array of Strings can be created:
- *
- *
- String[] array = ArrayUtils.toArray("1", "2");
- String[] emptyArray = ArrayUtils.<String>toArray();
- *
- *
- * The method is typically used in scenarios, where the caller itself uses generic types
- * that have to be combined into an array.
- *
- *
Note, this method makes only sense to provide arguments of the same type so that the
- * compiler can deduce the type of the array itself. While it is possible to select the
- * type explicitly like in
- * Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI)),
- * there is no real advantage when compared to
- * new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}.
- *
- * @param the array's element type
- * @param items the varargs array items, null allowed
- * @return the array, not null unless a null array is passed in
- * @since 3.0
- */
- public static T[] toArray(final T... items) {
- return items;
- }
-
- // Clone
- //-----------------------------------------------------------------------
- /**
- * Shallow clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
The objects in the array are not cloned, thus there is no special
- * handling for multi-dimensional arrays.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param the component type of the array
- * @param array the array to shallow clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static T[] clone(final T[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- * Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static long[] clone(final long[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static int[] clone(final int[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static short[] clone(final short[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static char[] clone(final char[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static byte[] clone(final byte[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static double[] clone(final double[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static float[] clone(final float[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- /**
- *
Clones an array returning a typecast result and handling
- * {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array the array to clone, may be {@code null}
- * @return the cloned array, {@code null} if {@code null} input
- */
- public static boolean[] clone(final boolean[] array) {
- if (array == null) {
- return null;
- }
- return array.clone();
- }
-
- // nullToEmpty
- //-----------------------------------------------------------------------
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- * @param array the array to check for {@code null} or empty
- * @param type the class representation of the desired array
- * @param the class type
- * @return the same array, {@code public static} empty array if {@code null}
- * @throws IllegalArgumentException if the type argument is null
- * @since 3.5
- */
- public static T[] nullToEmpty(final T[] array, final Class type) {
- if (type == null) {
- throw new IllegalArgumentException("The type must not be null");
- }
-
- if (array == null) {
- return type.cast(Array.newInstance(type.getComponentType(), 0));
- }
- return array;
- }
-
-
- /**
- * Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Object[] nullToEmpty(final Object[] array) {
- if (isEmpty(array)) {
- return EMPTY_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 3.2
- */
- public static Class>[] nullToEmpty(final Class>[] array) {
- if (isEmpty(array)) {
- return EMPTY_CLASS_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static String[] nullToEmpty(final String[] array) {
- if (isEmpty(array)) {
- return EMPTY_STRING_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static long[] nullToEmpty(final long[] array) {
- if (isEmpty(array)) {
- return EMPTY_LONG_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static int[] nullToEmpty(final int[] array) {
- if (isEmpty(array)) {
- return EMPTY_INT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static short[] nullToEmpty(final short[] array) {
- if (isEmpty(array)) {
- return EMPTY_SHORT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static char[] nullToEmpty(final char[] array) {
- if (isEmpty(array)) {
- return EMPTY_CHAR_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static byte[] nullToEmpty(final byte[] array) {
- if (isEmpty(array)) {
- return EMPTY_BYTE_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static double[] nullToEmpty(final double[] array) {
- if (isEmpty(array)) {
- return EMPTY_DOUBLE_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static float[] nullToEmpty(final float[] array) {
- if (isEmpty(array)) {
- return EMPTY_FLOAT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static boolean[] nullToEmpty(final boolean[] array) {
- if (isEmpty(array)) {
- return EMPTY_BOOLEAN_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Long[] nullToEmpty(final Long[] array) {
- if (isEmpty(array)) {
- return EMPTY_LONG_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Integer[] nullToEmpty(final Integer[] array) {
- if (isEmpty(array)) {
- return EMPTY_INTEGER_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Short[] nullToEmpty(final Short[] array) {
- if (isEmpty(array)) {
- return EMPTY_SHORT_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Character[] nullToEmpty(final Character[] array) {
- if (isEmpty(array)) {
- return EMPTY_CHARACTER_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Byte[] nullToEmpty(final Byte[] array) {
- if (isEmpty(array)) {
- return EMPTY_BYTE_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Double[] nullToEmpty(final Double[] array) {
- if (isEmpty(array)) {
- return EMPTY_DOUBLE_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Float[] nullToEmpty(final Float[] array) {
- if (isEmpty(array)) {
- return EMPTY_FLOAT_OBJECT_ARRAY;
- }
- return array;
- }
-
- /**
- *
Defensive programming technique to change a {@code null}
- * reference to an empty one.
- *
- *
This method returns an empty array for a {@code null} input array.
- *
- *
As a memory optimizing technique an empty array passed in will be overridden with
- * the empty {@code public static} references in this class.
- *
- * @param array the array to check for {@code null} or empty
- * @return the same array, {@code public static} empty array if {@code null} or empty input
- * @since 2.5
- */
- public static Boolean[] nullToEmpty(final Boolean[] array) {
- if (isEmpty(array)) {
- return EMPTY_BOOLEAN_OBJECT_ARRAY;
- }
- return array;
- }
-
- // Subarrays
- //-----------------------------------------------------------------------
- /**
- *
Produces a new array containing the elements between
- * the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- *
The component type of the subarray is always the same as
- * that of the input array. Thus, if the input is an array of type
- * {@code Date}, the following usage is envisaged:
- *
- *
- * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
- *
- *
- * @param the component type of the array
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(Object[], int, int)
- */
- public static T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- final Class> type = array.getClass().getComponentType();
- if (newSize <= 0) {
- @SuppressWarnings("unchecked") // OK, because array is of type T
- final T[] emptyArray = (T[]) Array.newInstance(type, 0);
- return emptyArray;
- }
- @SuppressWarnings("unchecked") // OK, because array is of type T
- final
- T[] subarray = (T[]) Array.newInstance(type, newSize);
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- * Produces a new {@code long} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(long[], int, int)
- */
- public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_LONG_ARRAY;
- }
-
- final long[] subarray = new long[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code int} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(int[], int, int)
- */
- public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_INT_ARRAY;
- }
-
- final int[] subarray = new int[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code short} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(short[], int, int)
- */
- public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_SHORT_ARRAY;
- }
-
- final short[] subarray = new short[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code char} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(char[], int, int)
- */
- public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_CHAR_ARRAY;
- }
-
- final char[] subarray = new char[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code byte} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(byte[], int, int)
- */
- public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_BYTE_ARRAY;
- }
-
- final byte[] subarray = new byte[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code double} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(double[], int, int)
- */
- public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_DOUBLE_ARRAY;
- }
-
- final double[] subarray = new double[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code float} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(float[], int, int)
- */
- public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_FLOAT_ARRAY;
- }
-
- final float[] subarray = new float[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- /**
- *
Produces a new {@code boolean} array containing the elements
- * between the start and end indices.
- *
- *
The start index is inclusive, the end index exclusive.
- * Null array input produces null output.
- *
- * @param array the array
- * @param startIndexInclusive the starting index. Undervalue (<0)
- * is promoted to 0, overvalue (>array.length) results
- * in an empty array.
- * @param endIndexExclusive elements up to endIndex-1 are present in the
- * returned subarray. Undervalue (< startIndex) produces
- * empty array, overvalue (>array.length) is demoted to
- * array length.
- * @return a new array containing the elements between
- * the start and end indices.
- * @since 2.1
- * @see Arrays#copyOfRange(boolean[], int, int)
- */
- public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
- if (array == null) {
- return null;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive > array.length) {
- endIndexExclusive = array.length;
- }
- final int newSize = endIndexExclusive - startIndexInclusive;
- if (newSize <= 0) {
- return EMPTY_BOOLEAN_ARRAY;
- }
-
- final boolean[] subarray = new boolean[newSize];
- System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
- return subarray;
- }
-
- // Is same length
- //-----------------------------------------------------------------------
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- *
Any multi-dimensional aspects of the arrays are ignored.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final Object[] array1, final Object[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final long[] array1, final long[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final int[] array1, final int[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final short[] array1, final short[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final char[] array1, final char[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final byte[] array1, final byte[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final double[] array1, final double[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final float[] array1, final float[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- /**
- *
Checks whether two arrays are the same length, treating
- * {@code null} arrays as length {@code 0}.
- *
- * @param array1 the first array, may be {@code null}
- * @param array2 the second array, may be {@code null}
- * @return {@code true} if length of arrays matches, treating
- * {@code null} as an empty array
- */
- public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
- return getLength(array1) == getLength(array2);
- }
-
- //-----------------------------------------------------------------------
- /**
- *
Returns the length of the specified array.
- * This method can deal with {@code Object} arrays and with primitive arrays.
- *
- *
If the input array is {@code null}, {@code 0} is returned.
- *
- *
- * ArrayUtils.getLength(null) = 0
- * ArrayUtils.getLength([]) = 0
- * ArrayUtils.getLength([null]) = 1
- * ArrayUtils.getLength([true, false]) = 2
- * ArrayUtils.getLength([1, 2, 3]) = 3
- * ArrayUtils.getLength(["a", "b", "c"]) = 3
- *
- *
- * @param array the array to retrieve the length from, may be null
- * @return The length of the array, or {@code 0} if the array is {@code null}
- * @throws IllegalArgumentException if the object argument is not an array.
- * @since 2.1
- */
- public static int getLength(final Object array) {
- if (array == null) {
- return 0;
- }
- return Array.getLength(array);
- }
-
- /**
- * Checks whether two arrays are the same type taking into account
- * multi-dimensional arrays.
- *
- * @param array1 the first array, must not be {@code null}
- * @param array2 the second array, must not be {@code null}
- * @return {@code true} if type of arrays matches
- * @throws IllegalArgumentException if either array is {@code null}
- */
- public static boolean isSameType(final Object array1, final Object array2) {
- if (array1 == null || array2 == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- return array1.getClass().getName().equals(array2.getClass().getName());
- }
-
- // Reverse
- //-----------------------------------------------------------------------
- /**
- *
Reverses the order of the given array.
- *
- *
There is no special handling for multi-dimensional arrays.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final Object[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final long[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final int[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final short[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final char[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final byte[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final double[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final float[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
Reverses the order of the given array.
- *
- *
This method does nothing for a {@code null} input array.
- *
- * @param array the array to reverse, may be {@code null}
- */
- public static void reverse(final boolean[] array) {
- if (array == null) {
- return;
- }
- reverse(array, 0, array.length);
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- boolean tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- byte tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- char tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- double tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- float tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- int tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- long tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Under value (<0) is promoted to 0, over value (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Under value (< start index) results in no
- * change. Over value (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- Object tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- /**
- *
- * Reverses the order of the given array in the given range.
- *
- *
- * This method does nothing for a {@code null} input array.
- *
- * @param array
- * the array to reverse, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @since 3.2
- */
- public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
- if (array == null) {
- return;
- }
- int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
- int j = Math.min(array.length, endIndexExclusive) - 1;
- short tmp;
- while (j > i) {
- tmp = array[j];
- array[j] = array[i];
- array[i] = tmp;
- j--;
- i++;
- }
- }
-
- // Swap
- //-----------------------------------------------------------------------
- /**
- * Swaps two elements in the given array.
- *
- *
There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap(["1", "2", "3"], 0, 2) -> ["3", "2", "1"]
- * ArrayUtils.swap(["1", "2", "3"], 0, 0) -> ["1", "2", "3"]
- * ArrayUtils.swap(["1", "2", "3"], 1, 0) -> ["2", "1", "3"]
- * ArrayUtils.swap(["1", "2", "3"], 0, 5) -> ["1", "2", "3"]
- * ArrayUtils.swap(["1", "2", "3"], -1, 1) -> ["2", "1", "3"]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final Object[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given long array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([true, false, true], 0, 2) -> [true, false, true]
- * ArrayUtils.swap([true, false, true], 0, 0) -> [true, false, true]
- * ArrayUtils.swap([true, false, true], 1, 0) -> [false, true, true]
- * ArrayUtils.swap([true, false, true], 0, 5) -> [true, false, true]
- * ArrayUtils.swap([true, false, true], -1, 1) -> [false, true, true]
- *
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final long[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given int array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final int[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given short array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final short[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given char array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final char[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given byte array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final byte[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given double array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final double[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given float array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final float[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps two elements in the given boolean array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for a {@code null} or empty input array or for overflow indices.
- * Negative indices are promoted to 0(zero).
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
- * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
- * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element to swap
- * @param offset2 the index of the second element to swap
- * @since 3.5
- */
- public static void swap(final boolean[] array, final int offset1, final int offset2) {
- if (array == null || array.length == 0) {
- return;
- }
- swap(array, offset1, offset2, 1);
- }
-
- /**
- * Swaps a series of elements in the given boolean array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([true, false, true, false], 0, 2, 1) -> [true, false, true, false]
- * ArrayUtils.swap([true, false, true, false], 0, 0, 1) -> [true, false, true, false]
- * ArrayUtils.swap([true, false, true, false], 0, 2, 2) -> [true, false, true, false]
- * ArrayUtils.swap([true, false, true, false], -3, 2, 2) -> [true, false, true, false]
- * ArrayUtils.swap([true, false, true, false], 0, 3, 3) -> [false, false, true, true]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final boolean[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final boolean aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given byte array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final byte[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final byte aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given char array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final char[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final char aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given double array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final double[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final double aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given float array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final float[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final float aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
-
- }
-
- /**
- * Swaps a series of elements in the given int array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final int[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final int aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given long array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final long[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final long aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -> ["3", "2", "1", "4"]
- * ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -> ["1", "2", "3", "4"]
- * ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -> ["3", "4", "1", "2"]
- * ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -> ["3", "4", "1", "2"]
- * ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -> ["4", "2", "3", "1"]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final Object[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final Object aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given short array.
- *
- * This method does nothing for a {@code null} or empty input array or
- * for overflow indices. Negative indices are promoted to 0(zero). If any
- * of the sub-arrays to swap falls outside of the given array, then the
- * swap is stopped at the end of the array and as many as possible elements
- * are swapped.
- *
- * Examples:
- *
- * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
- * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
- *
- *
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @since 3.5
- */
- public static void swap(final short[] array, int offset1, int offset2, int len) {
- if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
- return;
- }
- if (offset1 < 0) {
- offset1 = 0;
- }
- if (offset2 < 0) {
- offset2 = 0;
- }
- if (offset1 == offset2) {
- return;
- }
- len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
- for (int i = 0; i < len; i++, offset1++, offset2++) {
- final short aux = array[offset1];
- array[offset1] = array[offset2];
- array[offset2] = aux;
- }
- }
-
- // Shift
- //-----------------------------------------------------------------------
- /**
- * Shifts the order of the given array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final Object[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given long array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final long[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given int array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final int[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given short array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final short[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given char array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final char[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given byte array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final byte[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given double array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final double[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given float array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final float[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of the given boolean array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array the array to shift, may be {@code null}
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final boolean[] array, final int offset) {
- if (array == null) {
- return;
- }
- shift(array, 0, array.length, offset);
- }
-
- /**
- * Shifts the order of a series of elements in the given boolean array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given byte array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given char array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given double array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given float array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given int array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given long array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- /**
- * Shifts the order of a series of elements in the given short array.
- *
- * There is no special handling for multi-dimensional arrays. This method
- * does nothing for {@code null} or empty input arrays.
- *
- * @param array
- * the array to shift, may be {@code null}
- * @param startIndexInclusive
- * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
- * change.
- * @param endIndexExclusive
- * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
- * change. Overvalue (>array.length) is demoted to array length.
- * @param offset
- * The number of positions to rotate the elements. If the offset is larger than the number of elements to
- * rotate, than the effective offset is modulo the number of elements to rotate.
- * @since 3.5
- */
- public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
- if (array == null) {
- return;
- }
- if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
- return;
- }
- if (startIndexInclusive < 0) {
- startIndexInclusive = 0;
- }
- if (endIndexExclusive >= array.length) {
- endIndexExclusive = array.length;
- }
- int n = endIndexExclusive - startIndexInclusive;
- if (n <= 1) {
- return;
- }
- offset %= n;
- if (offset < 0) {
- offset += n;
- }
- // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
- // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
- while (n > 1 && offset > 0) {
- final int n_offset = n - offset;
-
- if (offset > n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
- n = offset;
- offset -= n_offset;
- } else if (offset < n_offset) {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- startIndexInclusive += offset;
- n = n_offset;
- } else {
- swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
- break;
- }
- }
- }
-
- // IndexOf search
- // ----------------------------------------------------------------------
-
- // Object IndexOf
- //-----------------------------------------------------------------------
- /**
- * Finds the index of the given object in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param objectToFind the object to find, may be {@code null}
- * @return the index of the object within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final Object[] array, final Object objectToFind) {
- return indexOf(array, objectToFind, 0);
- }
-
- /**
- *
Finds the index of the given object in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param objectToFind the object to find, may be {@code null}
- * @param startIndex the index to start searching at
- * @return the index of the object within the array starting at the index,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- if (objectToFind == null) {
- for (int i = startIndex; i < array.length; i++) {
- if (array[i] == null) {
- return i;
- }
- }
- } else {
- for (int i = startIndex; i < array.length; i++) {
- if (objectToFind.equals(array[i])) {
- return i;
- }
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given object within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param objectToFind the object to find, may be {@code null}
- * @return the last index of the object within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final Object[] array, final Object objectToFind) {
- return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given object in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
- * the array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param objectToFind the object to find, may be {@code null}
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the object within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- if (objectToFind == null) {
- for (int i = startIndex; i >= 0; i--) {
- if (array[i] == null) {
- return i;
- }
- }
- } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
- for (int i = startIndex; i >= 0; i--) {
- if (objectToFind.equals(array[i])) {
- return i;
- }
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the object is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param objectToFind the object to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final Object[] array, final Object objectToFind) {
- return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
- }
-
- // long IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final long[] array, final long valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final long[] array, final long valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final long[] array, final long valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // int IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final int[] array, final int valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final int[] array, final int valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final int[] array, final int valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // short IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final short[] array, final short valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final short[] array, final short valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final short[] array, final short valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // char IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- * @since 2.1
- */
- public static int indexOf(final char[] array, final char valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- * @since 2.1
- */
- public static int indexOf(final char[] array, final char valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- * @since 2.1
- */
- public static int lastIndexOf(final char[] array, final char valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- * @since 2.1
- */
- public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- * @since 2.1
- */
- public static boolean contains(final char[] array, final char valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // byte IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final byte[] array, final byte valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final byte[] array, final byte valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final byte[] array, final byte valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // double IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final double[] array, final double valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value within a given tolerance in the array.
- * This method will return the index of the first value which falls between the region
- * defined by valueToFind - tolerance and valueToFind + tolerance.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param tolerance tolerance of the search
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
- return indexOf(array, valueToFind, 0, tolerance);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- * This method will return the index of the first value which falls between the region
- * defined by valueToFind - tolerance and valueToFind + tolerance.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @param tolerance tolerance of the search
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- final double min = valueToFind - tolerance;
- final double max = valueToFind + tolerance;
- for (int i = startIndex; i < array.length; i++) {
- if (array[i] >= min && array[i] <= max) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final double[] array, final double valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value within a given tolerance in the array.
- * This method will return the index of the last value which falls between the region
- * defined by valueToFind - tolerance and valueToFind + tolerance.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param tolerance tolerance of the search
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- * This method will return the index of the last value which falls between the region
- * defined by valueToFind - tolerance and valueToFind + tolerance.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @param tolerance search for value within plus/minus this amount
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- final double min = valueToFind - tolerance;
- final double max = valueToFind + tolerance;
- for (int i = startIndex; i >= 0; i--) {
- if (array[i] >= min && array[i] <= max) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final double[] array, final double valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if a value falling within the given tolerance is in the
- * given array. If the array contains a value within the inclusive range
- * defined by (value - tolerance) to (value + tolerance).
- *
- *
The method returns {@code false} if a {@code null} array
- * is passed in.
- *
- * @param array the array to search
- * @param valueToFind the value to find
- * @param tolerance the array contains the tolerance of the search
- * @return true if value falling within tolerance is in array
- */
- public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
- return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
- }
-
- // float IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final float[] array, final float valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final float[] array, final float valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
- * array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final float[] array, final float valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // boolean IndexOf
- //-----------------------------------------------------------------------
- /**
- *
Finds the index of the given value in the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int indexOf(final boolean[] array, final boolean valueToFind) {
- return indexOf(array, valueToFind, 0);
- }
-
- /**
- *
Finds the index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
- *
- * @param array the array to search through for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the index to start searching at
- * @return the index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
- * array input
- */
- public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- startIndex = 0;
- }
- for (int i = startIndex; i < array.length; i++) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Finds the last index of the given value within the array.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
- * {@code null} array input.
- *
- * @param array the array to traverse backwards looking for the object, may be {@code null}
- * @param valueToFind the object to find
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
- return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
- }
-
- /**
- *
Finds the last index of the given value in the array starting at the given index.
- *
- *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
- *
- *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
- * the array length will search from the end of the array.
- *
- * @param array the array to traverse for looking for the object, may be {@code null}
- * @param valueToFind the value to find
- * @param startIndex the start index to traverse backwards from
- * @return the last index of the value within the array,
- * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
- */
- public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
- if (isEmpty(array)) {
- return INDEX_NOT_FOUND;
- }
- if (startIndex < 0) {
- return INDEX_NOT_FOUND;
- } else if (startIndex >= array.length) {
- startIndex = array.length - 1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (valueToFind == array[i]) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- *
Checks if the value is in the given array.
- *
- *
The method returns {@code false} if a {@code null} array is passed in.
- *
- * @param array the array to search through
- * @param valueToFind the value to find
- * @return {@code true} if the array contains the object
- */
- public static boolean contains(final boolean[] array, final boolean valueToFind) {
- return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
- }
-
- // Primitive/Object array converters
- // ----------------------------------------------------------------------
-
- // Character array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Characters to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Character} array, may be {@code null}
- * @return a {@code char} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static char[] toPrimitive(final Character[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_CHAR_ARRAY;
- }
- final char[] result = new char[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].charValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Character to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Character} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code char} array, {@code null} if null array input
- */
- public static char[] toPrimitive(final Character[] array, final char valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_CHAR_ARRAY;
- }
- final char[] result = new char[array.length];
- for (int i = 0; i < array.length; i++) {
- final Character b = array[i];
- result[i] = (b == null ? valueForNull : b.charValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive chars to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code char} array
- * @return a {@code Character} array, {@code null} if null array input
- */
- public static Character[] toObject(final char[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_CHARACTER_OBJECT_ARRAY;
- }
- final Character[] result = new Character[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Character.valueOf(array[i]);
- }
- return result;
- }
-
- // Long array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Longs to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Long} array, may be {@code null}
- * @return a {@code long} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static long[] toPrimitive(final Long[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_LONG_ARRAY;
- }
- final long[] result = new long[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].longValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Long to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Long} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code long} array, {@code null} if null array input
- */
- public static long[] toPrimitive(final Long[] array, final long valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_LONG_ARRAY;
- }
- final long[] result = new long[array.length];
- for (int i = 0; i < array.length; i++) {
- final Long b = array[i];
- result[i] = (b == null ? valueForNull : b.longValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive longs to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code long} array
- * @return a {@code Long} array, {@code null} if null array input
- */
- public static Long[] toObject(final long[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_LONG_OBJECT_ARRAY;
- }
- final Long[] result = new Long[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Long.valueOf(array[i]);
- }
- return result;
- }
-
- // Int array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Integers to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Integer} array, may be {@code null}
- * @return an {@code int} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static int[] toPrimitive(final Integer[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_INT_ARRAY;
- }
- final int[] result = new int[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].intValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Integer to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Integer} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return an {@code int} array, {@code null} if null array input
- */
- public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_INT_ARRAY;
- }
- final int[] result = new int[array.length];
- for (int i = 0; i < array.length; i++) {
- final Integer b = array[i];
- result[i] = (b == null ? valueForNull : b.intValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive ints to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array an {@code int} array
- * @return an {@code Integer} array, {@code null} if null array input
- */
- public static Integer[] toObject(final int[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_INTEGER_OBJECT_ARRAY;
- }
- final Integer[] result = new Integer[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Integer.valueOf(array[i]);
- }
- return result;
- }
-
- // Short array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Shorts to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Short} array, may be {@code null}
- * @return a {@code byte} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static short[] toPrimitive(final Short[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_SHORT_ARRAY;
- }
- final short[] result = new short[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].shortValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Short to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Short} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code byte} array, {@code null} if null array input
- */
- public static short[] toPrimitive(final Short[] array, final short valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_SHORT_ARRAY;
- }
- final short[] result = new short[array.length];
- for (int i = 0; i < array.length; i++) {
- final Short b = array[i];
- result[i] = (b == null ? valueForNull : b.shortValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive shorts to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code short} array
- * @return a {@code Short} array, {@code null} if null array input
- */
- public static Short[] toObject(final short[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_SHORT_OBJECT_ARRAY;
- }
- final Short[] result = new Short[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Short.valueOf(array[i]);
- }
- return result;
- }
-
- // Byte array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Bytes to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Byte} array, may be {@code null}
- * @return a {@code byte} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static byte[] toPrimitive(final Byte[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BYTE_ARRAY;
- }
- final byte[] result = new byte[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].byteValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Bytes to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Byte} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code byte} array, {@code null} if null array input
- */
- public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BYTE_ARRAY;
- }
- final byte[] result = new byte[array.length];
- for (int i = 0; i < array.length; i++) {
- final Byte b = array[i];
- result[i] = (b == null ? valueForNull : b.byteValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive bytes to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code byte} array
- * @return a {@code Byte} array, {@code null} if null array input
- */
- public static Byte[] toObject(final byte[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BYTE_OBJECT_ARRAY;
- }
- final Byte[] result = new Byte[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Byte.valueOf(array[i]);
- }
- return result;
- }
-
- // Double array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Doubles to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Double} array, may be {@code null}
- * @return a {@code double} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static double[] toPrimitive(final Double[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_DOUBLE_ARRAY;
- }
- final double[] result = new double[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].doubleValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Doubles to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Double} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code double} array, {@code null} if null array input
- */
- public static double[] toPrimitive(final Double[] array, final double valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_DOUBLE_ARRAY;
- }
- final double[] result = new double[array.length];
- for (int i = 0; i < array.length; i++) {
- final Double b = array[i];
- result[i] = (b == null ? valueForNull : b.doubleValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive doubles to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code double} array
- * @return a {@code Double} array, {@code null} if null array input
- */
- public static Double[] toObject(final double[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_DOUBLE_OBJECT_ARRAY;
- }
- final Double[] result = new Double[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Double.valueOf(array[i]);
- }
- return result;
- }
-
- // Float array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Floats to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Float} array, may be {@code null}
- * @return a {@code float} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static float[] toPrimitive(final Float[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_FLOAT_ARRAY;
- }
- final float[] result = new float[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].floatValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Floats to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Float} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code float} array, {@code null} if null array input
- */
- public static float[] toPrimitive(final Float[] array, final float valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_FLOAT_ARRAY;
- }
- final float[] result = new float[array.length];
- for (int i = 0; i < array.length; i++) {
- final Float b = array[i];
- result[i] = (b == null ? valueForNull : b.floatValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive floats to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code float} array
- * @return a {@code Float} array, {@code null} if null array input
- */
- public static Float[] toObject(final float[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_FLOAT_OBJECT_ARRAY;
- }
- final Float[] result = new Float[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = Float.valueOf(array[i]);
- }
- return result;
- }
-
- /**
- *
Create an array of primitive type from an array of wrapper types.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array an array of wrapper object
- * @return an array of the corresponding primitive type, or the original array
- * @since 3.5
- */
- public static Object toPrimitive(final Object array) {
- if (array == null) {
- return null;
- }
- final Class> ct = array.getClass().getComponentType();
- final Class> pt = ClassUtils.wrapperToPrimitive(ct);
- if(Integer.TYPE.equals(pt)) {
- return toPrimitive((Integer[]) array);
- }
- if(Long.TYPE.equals(pt)) {
- return toPrimitive((Long[]) array);
- }
- if(Short.TYPE.equals(pt)) {
- return toPrimitive((Short[]) array);
- }
- if(Double.TYPE.equals(pt)) {
- return toPrimitive((Double[]) array);
- }
- if(Float.TYPE.equals(pt)) {
- return toPrimitive((Float[]) array);
- }
- return array;
- }
-
- // Boolean array converters
- // ----------------------------------------------------------------------
- /**
- *
Converts an array of object Booleans to primitives.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Boolean} array, may be {@code null}
- * @return a {@code boolean} array, {@code null} if null array input
- * @throws NullPointerException if array content is {@code null}
- */
- public static boolean[] toPrimitive(final Boolean[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BOOLEAN_ARRAY;
- }
- final boolean[] result = new boolean[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].booleanValue();
- }
- return result;
- }
-
- /**
- *
Converts an array of object Booleans to primitives handling {@code null}.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code Boolean} array, may be {@code null}
- * @param valueForNull the value to insert if {@code null} found
- * @return a {@code boolean} array, {@code null} if null array input
- */
- public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BOOLEAN_ARRAY;
- }
- final boolean[] result = new boolean[array.length];
- for (int i = 0; i < array.length; i++) {
- final Boolean b = array[i];
- result[i] = (b == null ? valueForNull : b.booleanValue());
- }
- return result;
- }
-
- /**
- *
Converts an array of primitive booleans to objects.
- *
- *
This method returns {@code null} for a {@code null} input array.
- *
- * @param array a {@code boolean} array
- * @return a {@code Boolean} array, {@code null} if null array input
- */
- public static Boolean[] toObject(final boolean[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_BOOLEAN_OBJECT_ARRAY;
- }
- final Boolean[] result = new Boolean[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
- }
- return result;
- }
-
- // ----------------------------------------------------------------------
- /**
- *
Checks if an array of Objects is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final Object[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive longs is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final long[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive ints is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final int[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive shorts is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final short[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive chars is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final char[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive bytes is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final byte[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive doubles is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final double[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive floats is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final float[] array) {
- return getLength(array) == 0;
- }
-
- /**
- *
Checks if an array of primitive booleans is empty or {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is empty or {@code null}
- * @since 2.1
- */
- public static boolean isEmpty(final boolean[] array) {
- return getLength(array) == 0;
- }
-
- // ----------------------------------------------------------------------
- /**
- *
Checks if an array of Objects is not empty and not {@code null}.
- *
- * @param the component type of the array
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final T[] array) {
- return !isEmpty(array);
- }
-
- /**
- * Checks if an array of primitive longs is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final long[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive ints is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final int[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive shorts is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final short[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive chars is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final char[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive bytes is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final byte[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive doubles is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final double[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive floats is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final float[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Checks if an array of primitive booleans is not empty and not {@code null}.
- *
- * @param array the array to test
- * @return {@code true} if the array is not empty and not {@code null}
- * @since 2.5
- */
- public static boolean isNotEmpty(final boolean[] array) {
- return !isEmpty(array);
- }
-
- /**
- *
Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(null, null) = null
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- * ArrayUtils.addAll([null], [null]) = [null, null]
- * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
- *
- *
- * @param the component type of the array
- * @param array1 the first array whose elements are added to the new array, may be {@code null}
- * @param array2 the second array whose elements are added to the new array, may be {@code null}
- * @return The new array, {@code null} if both arrays are {@code null}.
- * The type of the new array is the type of the first array,
- * unless the first array is null, in which case the type is the same as the second array.
- * @since 2.1
- * @throws IllegalArgumentException if the array types are incompatible
- */
- public static T[] addAll(final T[] array1, final T... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final Class> type1 = array1.getClass().getComponentType();
- @SuppressWarnings("unchecked") // OK, because array is of type T
- final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- try {
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- } catch (final ArrayStoreException ase) {
- // Check if problem was due to incompatible types
- /*
- * We do this here, rather than before the copy because:
- * - it would be a wasted check most of the time
- * - safer, in case check turns out to be too strict
- */
- final Class> type2 = array2.getClass().getComponentType();
- if (!type1.isAssignableFrom(type2)) {
- throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
- + type1.getName(), ase);
- }
- throw ase; // No, so rethrow original
- }
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new boolean[] array.
- * @since 2.1
- */
- public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final boolean[] joinedArray = new boolean[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new char[] array.
- * @since 2.1
- */
- public static char[] addAll(final char[] array1, final char... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final char[] joinedArray = new char[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new byte[] array.
- * @since 2.1
- */
- public static byte[] addAll(final byte[] array1, final byte... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final byte[] joinedArray = new byte[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new short[] array.
- * @since 2.1
- */
- public static short[] addAll(final short[] array1, final short... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final short[] joinedArray = new short[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new int[] array.
- * @since 2.1
- */
- public static int[] addAll(final int[] array1, final int... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final int[] joinedArray = new int[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new long[] array.
- * @since 2.1
- */
- public static long[] addAll(final long[] array1, final long... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final long[] joinedArray = new long[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new float[] array.
- * @since 2.1
- */
- public static float[] addAll(final float[] array1, final float... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final float[] joinedArray = new float[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Adds all the elements of the given arrays into a new array.
- *
The new array contains all of the element of {@code array1} followed
- * by all of the elements {@code array2}. When an array is returned, it is always
- * a new array.
- *
- *
- * ArrayUtils.addAll(array1, null) = cloned copy of array1
- * ArrayUtils.addAll(null, array2) = cloned copy of array2
- * ArrayUtils.addAll([], []) = []
- *
- *
- * @param array1 the first array whose elements are added to the new array.
- * @param array2 the second array whose elements are added to the new array.
- * @return The new double[] array.
- * @since 2.1
- */
- public static double[] addAll(final double[] array1, final double... array2) {
- if (array1 == null) {
- return clone(array2);
- } else if (array2 == null) {
- return clone(array1);
- }
- final double[] joinedArray = new double[array1.length + array2.length];
- System.arraycopy(array1, 0, joinedArray, 0, array1.length);
- System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
- return joinedArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element, unless the element itself is null,
- * in which case the return type is Object[]
- *
- *
- * ArrayUtils.add(null, null) = IllegalArgumentException
- * ArrayUtils.add(null, "a") = ["a"]
- * ArrayUtils.add(["a"], null) = ["a", null]
- * ArrayUtils.add(["a"], "b") = ["a", "b"]
- * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
- *
- *
- * @param the component type of the array
- * @param array the array to "add" the element to, may be {@code null}
- * @param element the object to add, may be {@code null}
- * @return A new array containing the existing elements plus the new element
- * The returned array type will be that of the input array (unless null),
- * in which case it will have the same type as the element.
- * If both are null, an IllegalArgumentException is thrown
- * @since 2.1
- * @throws IllegalArgumentException if both arguments are null
- */
- public static T[] add(final T[] array, final T element) {
- Class> type;
- if (array != null) {
- type = array.getClass().getComponentType();
- } else if (element != null) {
- type = element.getClass();
- } else {
- throw new IllegalArgumentException("Arguments cannot both be null");
- }
- @SuppressWarnings("unchecked") // type must be T
- final
- T[] newArray = (T[]) copyArrayGrow1(array, type);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, true) = [true]
- * ArrayUtils.add([true], false) = [true, false]
- * ArrayUtils.add([true, false], true) = [true, false, true]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static boolean[] add(final boolean[] array, final boolean element) {
- final boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static byte[] add(final byte[] array, final byte element) {
- final byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, '0') = ['0']
- * ArrayUtils.add(['1'], '0') = ['1', '0']
- * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static char[] add(final char[] array, final char element) {
- final char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static double[] add(final double[] array, final double element) {
- final double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static float[] add(final float[] array, final float element) {
- final float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static int[] add(final int[] array, final int element) {
- final int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static long[] add(final long[] array, final long element) {
- final long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Copies the given array and adds the given element at the end of the new array.
- *
- *
The new array contains the same elements of the input
- * array plus the given element in the last position. The component type of
- * the new array is the same as that of the input array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0) = [0]
- * ArrayUtils.add([1], 0) = [1, 0]
- * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
- *
- *
- * @param array the array to copy and add the element to, may be {@code null}
- * @param element the object to add at the last index of the new array
- * @return A new array containing the existing elements plus the new element
- * @since 2.1
- */
- public static short[] add(final short[] array, final short element) {
- final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
- newArray[newArray.length - 1] = element;
- return newArray;
- }
-
- /**
- * Returns a copy of the given array of size 1 greater than the argument.
- * The last value of the array is left to the default value.
- *
- * @param array The array to copy, must not be {@code null}.
- * @param newArrayComponentType If {@code array} is {@code null}, create a
- * size 1 array of this type.
- * @return A new copy of the array of size 1 greater than the input.
- */
- private static Object copyArrayGrow1(final Object array, final Class> newArrayComponentType) {
- if (array != null) {
- final int arrayLength = Array.getLength(array);
- final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
- System.arraycopy(array, 0, newArray, 0, arrayLength);
- return newArray;
- }
- return Array.newInstance(newArrayComponentType, 1);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0, null) = IllegalArgumentException
- * ArrayUtils.add(null, 0, "a") = ["a"]
- * ArrayUtils.add(["a"], 1, null) = ["a", null]
- * ArrayUtils.add(["a"], 1, "b") = ["a", "b"]
- * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
- *
- *
- * @param the component type of the array
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > array.length).
- * @throws IllegalArgumentException if both array and element are null
- * @deprecated this method has been superseded by {@link #insert(int, Object[], Object...) insert(int, T[], T...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static T[] add(final T[] array, final int index, final T element) {
- Class> clss = null;
- if (array != null) {
- clss = array.getClass().getComponentType();
- } else if (element != null) {
- clss = element.getClass();
- } else {
- throw new IllegalArgumentException("Array and element cannot both be null");
- }
- @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
- final T[] newArray = (T[]) add(array, index, element, clss);
- return newArray;
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0, true) = [true]
- * ArrayUtils.add([true], 0, false) = [false, true]
- * ArrayUtils.add([false], 1, true) = [false, true]
- * ArrayUtils.add([true, false], 1, true) = [true, true, false]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, boolean[], boolean...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static boolean[] add(final boolean[] array, final int index, final boolean element) {
- return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add(null, 0, 'a') = ['a']
- * ArrayUtils.add(['a'], 0, 'b') = ['b', 'a']
- * ArrayUtils.add(['a', 'b'], 0, 'c') = ['c', 'a', 'b']
- * ArrayUtils.add(['a', 'b'], 1, 'k') = ['a', 'k', 'b']
- * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, char[], char...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static char[] add(final char[] array, final int index, final char element) {
- return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1], 0, 2) = [2, 1]
- * ArrayUtils.add([2, 6], 2, 3) = [2, 6, 3]
- * ArrayUtils.add([2, 6], 0, 1) = [1, 2, 6]
- * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, byte[], byte...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static byte[] add(final byte[] array, final int index, final byte element) {
- return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1], 0, 2) = [2, 1]
- * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10]
- * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6]
- * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, short[], short...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static short[] add(final short[] array, final int index, final short element) {
- return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1], 0, 2) = [2, 1]
- * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10]
- * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6]
- * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, int[], int...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static int[] add(final int[] array, final int index, final int element) {
- return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1L], 0, 2L) = [2L, 1L]
- * ArrayUtils.add([2L, 6L], 2, 10L) = [2L, 6L, 10L]
- * ArrayUtils.add([2L, 6L], 0, -4L) = [-4L, 2L, 6L]
- * ArrayUtils.add([2L, 6L, 3L], 2, 1L) = [2L, 6L, 1L, 3L]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, long[], long...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static long[] add(final long[] array, final int index, final long element) {
- return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1.1f], 0, 2.2f) = [2.2f, 1.1f]
- * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f) = [2.3f, 6.4f, 10.5f]
- * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f) = [-4.8f, 2.6f, 6.7f]
- * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f) = [2.9f, 6.0f, 1.0f, 0.3f]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, float[], float...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static float[] add(final float[] array, final int index, final float element) {
- return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
- }
-
- /**
- * Inserts the specified element at the specified position in the array.
- * Shifts the element currently at that position (if any) and any subsequent
- * elements to the right (adds one to their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array plus the given element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, a new one element array is returned
- * whose component type is the same as the element.
- *
- *
- * ArrayUtils.add([1.1], 0, 2.2) = [2.2, 1.1]
- * ArrayUtils.add([2.3, 6.4], 2, 10.5) = [2.3, 6.4, 10.5]
- * ArrayUtils.add([2.6, 6.7], 0, -4.8) = [-4.8, 2.6, 6.7]
- * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0) = [2.9, 6.0, 1.0, 0.3]
- *
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @return A new array containing the existing elements and the new element
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index > array.length).
- * @deprecated this method has been superseded by {@link #insert(int, double[], double...)} and
- * may be removed in a future release. Please note the handling of {@code null} input arrays differs
- * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
- */
- @Deprecated
- public static double[] add(final double[] array, final int index, final double element) {
- return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
- }
-
- /**
- * Underlying implementation of add(array, index, element) methods.
- * The last parameter is the class, which may not equal element.getClass
- * for primitives.
- *
- * @param array the array to add the element to, may be {@code null}
- * @param index the position of the new object
- * @param element the object to add
- * @param clss the type of the element being added
- * @return A new array containing the existing elements and the new element
- */
- private static Object add(final Object array, final int index, final Object element, final Class> clss) {
- if (array == null) {
- if (index != 0) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
- }
- final Object joinedArray = Array.newInstance(clss, 1);
- Array.set(joinedArray, 0, element);
- return joinedArray;
- }
- final int length = Array.getLength(array);
- if (index > length || index < 0) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
- }
- final Object result = Array.newInstance(clss, length + 1);
- System.arraycopy(array, 0, result, 0, index);
- Array.set(result, index, element);
- if (index < length) {
- System.arraycopy(array, index, result, index + 1, length - index);
- }
- return result;
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove(["a"], 0) = []
- * ArrayUtils.remove(["a", "b"], 0) = ["b"]
- * ArrayUtils.remove(["a", "b"], 1) = ["a"]
- * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
- *
- *
- * @param the component type of the array
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
- public static T[] remove(final T[] array, final int index) {
- return (T[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, "a") = null
- * ArrayUtils.removeElement([], "a") = []
- * ArrayUtils.removeElement(["a"], "b") = ["a"]
- * ArrayUtils.removeElement(["a", "b"], "a") = ["b"]
- * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
- *
- *
- * @param the component type of the array
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static T[] removeElement(final T[] array, final Object element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([true], 0) = []
- * ArrayUtils.remove([true, false], 0) = [false]
- * ArrayUtils.remove([true, false], 1) = [true]
- * ArrayUtils.remove([true, true, false], 1) = [true, false]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static boolean[] remove(final boolean[] array, final int index) {
- return (boolean[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, true) = null
- * ArrayUtils.removeElement([], true) = []
- * ArrayUtils.removeElement([true], false) = [true]
- * ArrayUtils.removeElement([true, false], false) = [true]
- * ArrayUtils.removeElement([true, false, true], true) = [false, true]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static boolean[] removeElement(final boolean[] array, final boolean element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1], 0) = []
- * ArrayUtils.remove([1, 0], 0) = [0]
- * ArrayUtils.remove([1, 0], 1) = [1]
- * ArrayUtils.remove([1, 0, 1], 1) = [1, 1]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static byte[] remove(final byte[] array, final int index) {
- return (byte[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1) = null
- * ArrayUtils.removeElement([], 1) = []
- * ArrayUtils.removeElement([1], 0) = [1]
- * ArrayUtils.removeElement([1, 0], 0) = [1]
- * ArrayUtils.removeElement([1, 0, 1], 1) = [0, 1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static byte[] removeElement(final byte[] array, final byte element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove(['a'], 0) = []
- * ArrayUtils.remove(['a', 'b'], 0) = ['b']
- * ArrayUtils.remove(['a', 'b'], 1) = ['a']
- * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static char[] remove(final char[] array, final int index) {
- return (char[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 'a') = null
- * ArrayUtils.removeElement([], 'a') = []
- * ArrayUtils.removeElement(['a'], 'b') = ['a']
- * ArrayUtils.removeElement(['a', 'b'], 'a') = ['b']
- * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static char[] removeElement(final char[] array, final char element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1.1], 0) = []
- * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
- * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
- * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static double[] remove(final double[] array, final int index) {
- return (double[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1.1) = null
- * ArrayUtils.removeElement([], 1.1) = []
- * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
- * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
- * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static double[] removeElement(final double[] array, final double element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1.1], 0) = []
- * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
- * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
- * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static float[] remove(final float[] array, final int index) {
- return (float[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1.1) = null
- * ArrayUtils.removeElement([], 1.1) = []
- * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
- * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
- * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static float[] removeElement(final float[] array, final float element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1], 0) = []
- * ArrayUtils.remove([2, 6], 0) = [6]
- * ArrayUtils.remove([2, 6], 1) = [2]
- * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static int[] remove(final int[] array, final int index) {
- return (int[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1) = null
- * ArrayUtils.removeElement([], 1) = []
- * ArrayUtils.removeElement([1], 2) = [1]
- * ArrayUtils.removeElement([1, 3], 1) = [3]
- * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static int[] removeElement(final int[] array, final int element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1], 0) = []
- * ArrayUtils.remove([2, 6], 0) = [6]
- * ArrayUtils.remove([2, 6], 1) = [2]
- * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static long[] remove(final long[] array, final int index) {
- return (long[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1) = null
- * ArrayUtils.removeElement([], 1) = []
- * ArrayUtils.removeElement([1], 2) = [1]
- * ArrayUtils.removeElement([1, 3], 1) = [3]
- * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static long[] removeElement(final long[] array, final long element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.remove([1], 0) = []
- * ArrayUtils.remove([2, 6], 0) = [6]
- * ArrayUtils.remove([2, 6], 1) = [2]
- * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- public static short[] remove(final short[] array, final int index) {
- return (short[]) remove((Object) array, index);
- }
-
- /**
- * Removes the first occurrence of the specified element from the
- * specified array. All subsequent elements are shifted to the left
- * (subtracts one from their indices). If the array doesn't contains
- * such an element, no elements are removed from the array.
- *
- *
This method returns a new array with the same elements of the input
- * array except the first occurrence of the specified element. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
- * ArrayUtils.removeElement(null, 1) = null
- * ArrayUtils.removeElement([], 1) = []
- * ArrayUtils.removeElement([1], 2) = [1]
- * ArrayUtils.removeElement([1, 3], 1) = [3]
- * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param element the element to be removed
- * @return A new array containing the existing elements except the first
- * occurrence of the specified element.
- * @since 2.1
- */
- public static short[] removeElement(final short[] array, final short element) {
- final int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
- return remove(array, index);
- }
-
- /**
- * Removes the element at the specified position from the specified array.
- * All subsequent elements are shifted to the left (subtracts one from
- * their indices).
- *
- *
This method returns a new array with the same elements of the input
- * array except the element on the specified position. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param index the position of the element to be removed
- * @return A new array containing the existing elements except the element
- * at the specified position.
- * @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 2.1
- */
- private static Object remove(final Object array, final int index) {
- final int length = getLength(array);
- if (index < 0 || index >= length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
- }
-
- final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
- System.arraycopy(array, 0, result, 0, index);
- if (index < length - 1) {
- System.arraycopy(array, index + 1, result, index, length - index - 1);
- }
-
- return result;
- }
-
- /**
- *
Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
- * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
- *
- *
- * @param the component type of the array
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
- public static T[] removeAll(final T[] array, final int... indices) {
- return (T[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, "a", "b") = null
- * ArrayUtils.removeElements([], "a", "b") = []
- * ArrayUtils.removeElements(["a"], "b", "c") = ["a"]
- * ArrayUtils.removeElements(["a", "b"], "a", "c") = ["b"]
- * ArrayUtils.removeElements(["a", "b", "a"], "a") = ["b", "a"]
- * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
- *
- *
- * @param the component type of the array
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- @SafeVarargs
- public static T[] removeElements(final T[] array, final T... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final T v : values) {
- final MutableInt count = occurrences.get(v);
- if (count == null) {
- occurrences.put(v, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final T key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
- final T[] result = (T[]) removeAll(array, toRemove);
- return result;
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static byte[] removeAll(final byte[] array, final int... indices) {
- return (byte[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static byte[] removeElements(final byte[] array, final byte... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final Map occurrences = new HashMap<>(values.length);
- for (final byte v : values) {
- final Byte boxed = Byte.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final byte key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (byte[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static short[] removeAll(final short[] array, final int... indices) {
- return (short[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static short[] removeElements(final short[] array, final short... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final short v : values) {
- final Short boxed = Short.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final short key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (short[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static int[] removeAll(final int[] array, final int... indices) {
- return (int[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static int[] removeElements(final int[] array, final int... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final int v : values) {
- final Integer boxed = Integer.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final int key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (int[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static char[] removeAll(final char[] array, final int... indices) {
- return (char[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static char[] removeElements(final char[] array, final char... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final char v : values) {
- final Character boxed = Character.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final char key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (char[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static long[] removeAll(final long[] array, final int... indices) {
- return (long[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static long[] removeElements(final long[] array, final long... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final long v : values) {
- final Long boxed = Long.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final long key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (long[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static float[] removeAll(final float[] array, final int... indices) {
- return (float[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static float[] removeElements(final float[] array, final float... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final float v : values) {
- final Float boxed = Float.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final float key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (float[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([1], 0) = []
- * ArrayUtils.removeAll([2, 6], 0) = [6]
- * ArrayUtils.removeAll([2, 6], 0, 1) = []
- * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
- * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
- * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static double[] removeAll(final double[] array, final int... indices) {
- return (double[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, 1, 2) = null
- * ArrayUtils.removeElements([], 1, 2) = []
- * ArrayUtils.removeElements([1], 2, 3) = [1]
- * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
- * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
- * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static double[] removeElements(final double[] array, final double... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(values.length);
- for (final double v : values) {
- final Double boxed = Double.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final double key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (double[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes the elements at the specified positions from the specified array.
- * All remaining elements are shifted to the left.
- *
- *
This method returns a new array with the same elements of the input
- * array except those at the specified positions. The component
- * type of the returned array is always the same as that of the input
- * array.
- *
- *
If the input array is {@code null}, an IndexOutOfBoundsException
- * will be thrown, because in that case no valid index can be specified.
- *
- *
- * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
- * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
- *
- *
- * @param array the array to remove the element from, may not be {@code null}
- * @param indices the positions of the elements to be removed
- * @return A new array containing the existing elements except those
- * at the specified positions.
- * @throws IndexOutOfBoundsException if any index is out of range
- * (index < 0 || index >= array.length), or if the array is {@code null}.
- * @since 3.0.1
- */
- public static boolean[] removeAll(final boolean[] array, final int... indices) {
- return (boolean[]) removeAll((Object) array, indices);
- }
-
- /**
- * Removes occurrences of specified elements, in specified quantities,
- * from the specified array. All subsequent elements are shifted left.
- * For any element-to-be-removed specified in greater quantities than
- * contained in the original array, no change occurs beyond the
- * removal of the existing matching items.
- *
- *
This method returns a new array with the same elements of the input
- * array except for the earliest-encountered occurrences of the specified
- * elements. The component type of the returned array is always the same
- * as that of the input array.
- *
- *
- * ArrayUtils.removeElements(null, true, false) = null
- * ArrayUtils.removeElements([], true, false) = []
- * ArrayUtils.removeElements([true], false, false) = [true]
- * ArrayUtils.removeElements([true, false], true, true) = [false]
- * ArrayUtils.removeElements([true, false, true], true) = [false, true]
- * ArrayUtils.removeElements([true, false, true], true, true) = [false]
- *
- *
- * @param array the array to remove the element from, may be {@code null}
- * @param values the elements to be removed
- * @return A new array containing the existing elements except the
- * earliest-encountered occurrences of the specified elements.
- * @since 3.0.1
- */
- public static boolean[] removeElements(final boolean[] array, final boolean... values) {
- if (isEmpty(array) || isEmpty(values)) {
- return clone(array);
- }
- final HashMap occurrences = new HashMap<>(2); // only two possible values here
- for (final boolean v : values) {
- final Boolean boxed = Boolean.valueOf(v);
- final MutableInt count = occurrences.get(boxed);
- if (count == null) {
- occurrences.put(boxed, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- final BitSet toRemove = new BitSet();
- for (int i = 0; i < array.length; i++) {
- final boolean key = array[i];
- final MutableInt count = occurrences.get(key);
- if (count != null) {
- if (count.decrementAndGet() == 0) {
- occurrences.remove(key);
- }
- toRemove.set(i);
- }
- }
- return (boolean[]) removeAll(array, toRemove);
- }
-
- /**
- * Removes multiple array elements specified by index.
- * @param array source
- * @param indices to remove
- * @return new array of same type minus elements specified by unique values of {@code indices}
- * @since 3.0.1
- */
- // package protected for access by unit tests
- static Object removeAll(final Object array, final int... indices) {
- final int length = getLength(array);
- int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
- final int[] clonedIndices = clone(indices);
- Arrays.sort(clonedIndices);
-
- // identify length of result array
- if (isNotEmpty(clonedIndices)) {
- int i = clonedIndices.length;
- int prevIndex = length;
- while (--i >= 0) {
- final int index = clonedIndices[i];
- if (index < 0 || index >= length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
- }
- if (index >= prevIndex) {
- continue;
- }
- diff++;
- prevIndex = index;
- }
- }
-
- // create result array
- final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
- if (diff < length) {
- int end = length; // index just after last copy
- int dest = length - diff; // number of entries so far not copied
- for (int i = clonedIndices.length - 1; i >= 0; i--) {
- final int index = clonedIndices[i];
- if (end - index > 1) { // same as (cp > 0)
- final int cp = end - index - 1;
- dest -= cp;
- System.arraycopy(array, index + 1, result, dest, cp);
- // Afer this copy, we still have room for dest items.
- }
- end = index;
- }
- if (end > 0) {
- System.arraycopy(array, 0, result, 0, end);
- }
- }
- return result;
- }
-
- /**
- * Removes multiple array elements specified by indices.
- *
- * @param array source
- * @param indices to remove
- * @return new array of same type minus elements specified by the set bits in {@code indices}
- * @since 3.2
- */
- // package protected for access by unit tests
- static Object removeAll(final Object array, final BitSet indices) {
- final int srcLength = getLength(array);
- // No need to check maxIndex here, because method only currently called from removeElements()
- // which guarantee to generate on;y valid bit entries.
-// final int maxIndex = indices.length();
-// if (maxIndex > srcLength) {
-// throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
-// }
- final int removals = indices.cardinality(); // true bits are items to remove
- final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
- int srcIndex = 0;
- int destIndex = 0;
- int count;
- int set;
- while ((set = indices.nextSetBit(srcIndex)) != -1) {
- count = set - srcIndex;
- if (count > 0) {
- System.arraycopy(array, srcIndex, result, destIndex, count);
- destIndex += count;
- }
- srcIndex = indices.nextClearBit(set);
- }
- count = srcLength - srcIndex;
- if (count > 0) {
- System.arraycopy(array, srcIndex, result, destIndex, count);
- }
- return result;
- }
-
- /**
- * This method checks whether the provided array is sorted according to the class's
- * {@code compareTo} method.
- *
- * @param array the array to check
- * @param the datatype of the array to check, it must implement {@code Comparable}
- * @return whether the array is sorted
- * @since 3.4
- */
- public static > boolean isSorted(final T[] array) {
- return isSorted(array, new Comparator() {
- @Override
- public int compare(final T o1, final T o2) {
- return o1.compareTo(o2);
- }
- });
- }
-
-
- /**
- * This method checks whether the provided array is sorted according to the provided {@code Comparator}.
- *
- * @param array the array to check
- * @param comparator the {@code Comparator} to compare over
- * @param the datatype of the array
- * @return whether the array is sorted
- * @since 3.4
- */
- public static boolean isSorted(final T[] array, final Comparator comparator) {
- if (comparator == null) {
- throw new IllegalArgumentException("Comparator should not be null.");
- }
-
- if (array == null || array.length < 2) {
- return true;
- }
-
- T previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final T current = array[i];
- if (comparator.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- * This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final int[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- int previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final int current = array[i];
- if (NumberUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final long[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- long previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final long current = array[i];
- if (NumberUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final short[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- short previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final short current = array[i];
- if (NumberUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final double[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- double previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final double current = array[i];
- if (Double.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final float[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- float previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final float current = array[i];
- if (Float.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final byte[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- byte previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final byte current = array[i];
- if (NumberUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering.
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final char[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- char previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final char current = array[i];
- if (CharUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- *
This method checks whether the provided array is sorted according to natural ordering
- * ({@code false} before {@code true}).
- *
- * @param array the array to check
- * @return whether the array is sorted according to natural ordering
- * @since 3.4
- */
- public static boolean isSorted(final boolean[] array) {
- if (array == null || array.length < 2) {
- return true;
- }
-
- boolean previous = array[0];
- final int n = array.length;
- for (int i = 1; i < n; i++) {
- final boolean current = array[i];
- if (BooleanUtils.compare(previous, current) > 0) {
- return false;
- }
-
- previous = current;
- }
- return true;
- }
-
- /**
- * Removes the occurrences of the specified element from the specified boolean array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified char array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static char[] removeAllOccurences(final char[] array, final char element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified byte array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static byte[] removeAllOccurences(final byte[] array, final byte element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified short array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static short[] removeAllOccurences(final short[] array, final short element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified int array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static int[] removeAllOccurences(final int[] array, final int element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified long array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static long[] removeAllOccurences(final long[] array, final long element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified float array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static float[] removeAllOccurences(final float[] array, final float element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified double array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static double[] removeAllOccurences(final double[] array, final double element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Removes the occurrences of the specified element from the specified array.
- *
- *
- * All subsequent elements are shifted to the left (subtracts one from their indices).
- * If the array doesn't contains such an element, no elements are removed from the array.
- * null will be returned if the input array is null.
- *
- *
- * @param the type of object in the array
- * @param element the element to remove
- * @param array the input array
- *
- * @return A new array containing the existing elements except the occurrences of the specified element.
- * @since 3.5
- */
- public static T[] removeAllOccurences(final T[] array, final T element) {
- int index = indexOf(array, element);
- if (index == INDEX_NOT_FOUND) {
- return clone(array);
- }
-
- final int[] indices = new int[array.length - index];
- indices[0] = index;
- int count = 1;
-
- while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
- indices[count++] = index;
- }
-
- return removeAll(array, Arrays.copyOf(indices, count));
- }
-
- /**
- * Returns an array containing the string representation of each element in the argument array.
- *
- * This method returns {@code null} for a {@code null} input array.
- *
- * @param array the {@code Object[]} to be processed, may be null
- * @return {@code String[]} of the same size as the source with its element's string representation,
- * {@code null} if null array input
- * @throws NullPointerException if array contains {@code null}
- * @since 3.6
- */
- public static String[] toStringArray(final Object[] array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_STRING_ARRAY;
- }
-
- final String[] result = new String[array.length];
- for (int i = 0; i < array.length; i++) {
- result[i] = array[i].toString();
- }
-
- return result;
- }
-
- /**
- * Returns an array containing the string representation of each element in the argument
- * array handling {@code null} elements.
- *
- * This method returns {@code null} for a {@code null} input array.
- *
- * @param array the Object[] to be processed, may be null
- * @param valueForNullElements the value to insert if {@code null} is found
- * @return a {@code String} array, {@code null} if null array input
- * @since 3.6
- */
- public static String[] toStringArray(final Object[] array, final String valueForNullElements) {
- if (null == array) {
- return null;
- } else if (array.length == 0) {
- return EMPTY_STRING_ARRAY;
- }
-
- final String[] result = new String[array.length];
- for (int i = 0; i < array.length; i++) {
- final Object object = array[i];
- result[i] = (object == null ? valueForNullElements : object.toString());
- }
-
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final boolean[] result = new boolean[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static byte[] insert(final int index, final byte[] array, final byte... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final byte[] result = new byte[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static char[] insert(final int index, final char[] array, final char... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final char[] result = new char[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static double[] insert(final int index, final double[] array, final double... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final double[] result = new double[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static float[] insert(final int index, final float[] array, final float... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final float[] result = new float[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static int[] insert(final int index, final int[] array, final int... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final int[] result = new int[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static long[] insert(final int index, final long[] array, final long... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final long[] result = new long[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- public static short[] insert(final int index, final short[] array, final short... values) {
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final short[] result = new short[array.length + values.length];
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Inserts elements into an array at the given index (starting from zero).
- *
- * When an array is returned, it is always a new array.
- *
- *
- * ArrayUtils.insert(index, null, null) = null
- * ArrayUtils.insert(index, array, null) = cloned copy of 'array'
- * ArrayUtils.insert(index, null, values) = null
- *
- *
- * @param The type of elements in {@code array} and {@code values}
- * @param index the position within {@code array} to insert the new values
- * @param array the array to insert the values into, may be {@code null}
- * @param values the new values to insert, may be {@code null}
- * @return The new array.
- * @throws IndexOutOfBoundsException if {@code array} is provided
- * and either {@code index < 0} or {@code index > array.length}
- * @since 3.6
- */
- @SafeVarargs
- public static T[] insert(final int index, final T[] array, final T... values) {
- /*
- * Note on use of @SafeVarargs:
- *
- * By returning null when 'array' is null, we avoid returning the vararg
- * array to the caller. We also avoid relying on the type of the vararg
- * array, by inspecting the component type of 'array'.
- */
-
- if (array == null) {
- return null;
- }
- if (values == null || values.length == 0) {
- return clone(array);
- }
- if (index < 0 || index > array.length) {
- throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
- }
-
- final Class> type = array.getClass().getComponentType();
- @SuppressWarnings("unchecked") // OK, because array and values are of type T
- final
- T[] result = (T[]) Array.newInstance(type, array.length + values.length);
-
- System.arraycopy(values, 0, result, index, values.length);
- if (index > 0) {
- System.arraycopy(array, 0, result, 0, index);
- }
- if (index < array.length) {
- System.arraycopy(array, index, result, index + values.length, array.length - index);
- }
- return result;
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final Object[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final Object[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final boolean[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final boolean[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final byte[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final byte[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final char[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final char[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final short[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final short[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final int[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final int[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final long[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final long[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final float[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final float[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final double[] array) {
- shuffle(array, new Random());
- }
-
- /**
- * Randomly permutes the elements of the specified array using the Fisher-Yates algorithm.
- *
- * @param array the array to shuffle
- * @param random the source of randomness used to permute the elements
- * @see Fisher-Yates shuffle algorithm
- * @since 3.6
- */
- public static void shuffle(final double[] array, final Random random) {
- for (int i = array.length; i > 1; i--) {
- swap(array, i - 1, random.nextInt(i), 1);
- }
- }
-
- /**
- * Returns whether a given array can safely be accessed at the given index.
- * @param the component type of the array
- * @param array the array to inspect, may be null
- * @param index the index of the array to be inspected
- * @return Whether the given index is safely-accessible in the given array
- * @since 3.8
- */
- public static boolean isArrayIndexValid(T[] array, int index){
- if(getLength(array) == 0 || array.length <= index){
- return false;
- }
-
- return index >= 0;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/BooleanUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/BooleanUtils.java
deleted file mode 100644
index 4694f093..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/BooleanUtils.java
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-/**
- * Operations on boolean primitives and Boolean objects.
- *
- * This class tries to handle {@code null} input gracefully.
- * An exception will not be thrown for a {@code null} input.
- * Each method documents its behaviour in more detail.
- *
- * #ThreadSafe#
- * @since 2.0
- */
-public class BooleanUtils {
-
- /**
- * {@code BooleanUtils} instances should NOT be constructed in standard programming.
- * Instead, the class should be used as {@code BooleanUtils.negate(true);}.
- *
- * This constructor is public to permit tools that require a JavaBean instance
- * to operate.
- */
- public BooleanUtils() {
- super();
- }
-
- // Boolean utilities
- //--------------------------------------------------------------------------
- /**
- * Negates the specified boolean.
- *
- * If {@code null} is passed in, {@code null} will be returned.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * BooleanUtils.negate(Boolean.TRUE) = Boolean.FALSE;
- * BooleanUtils.negate(Boolean.FALSE) = Boolean.TRUE;
- * BooleanUtils.negate(null) = null;
- *
- *
- * @param bool the Boolean to negate, may be null
- * @return the negated Boolean, or {@code null} if {@code null} input
- */
- public static Boolean negate(final Boolean bool) {
- if (bool == null) {
- return null;
- }
- return bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
- }
-
- // boolean Boolean methods
- //-----------------------------------------------------------------------
- /**
- * Checks if a {@code Boolean} value is {@code true},
- * handling {@code null} by returning {@code false}.
- *
- *
- * BooleanUtils.isTrue(Boolean.TRUE) = true
- * BooleanUtils.isTrue(Boolean.FALSE) = false
- * BooleanUtils.isTrue(null) = false
- *
- *
- * @param bool the boolean to check, null returns {@code false}
- * @return {@code true} only if the input is non-null and true
- * @since 2.1
- */
- public static boolean isTrue(final Boolean bool) {
- return Boolean.TRUE.equals(bool);
- }
-
- /**
- * Checks if a {@code Boolean} value is not {@code true},
- * handling {@code null} by returning {@code true}.
- *
- *
- * BooleanUtils.isNotTrue(Boolean.TRUE) = false
- * BooleanUtils.isNotTrue(Boolean.FALSE) = true
- * BooleanUtils.isNotTrue(null) = true
- *
- *
- * @param bool the boolean to check, null returns {@code true}
- * @return {@code true} if the input is null or false
- * @since 2.3
- */
- public static boolean isNotTrue(final Boolean bool) {
- return !isTrue(bool);
- }
-
- /**
- * Checks if a {@code Boolean} value is {@code false},
- * handling {@code null} by returning {@code false}.
- *
- *
- * BooleanUtils.isFalse(Boolean.TRUE) = false
- * BooleanUtils.isFalse(Boolean.FALSE) = true
- * BooleanUtils.isFalse(null) = false
- *
- *
- * @param bool the boolean to check, null returns {@code false}
- * @return {@code true} only if the input is non-null and false
- * @since 2.1
- */
- public static boolean isFalse(final Boolean bool) {
- return Boolean.FALSE.equals(bool);
- }
-
- /**
- * Checks if a {@code Boolean} value is not {@code false},
- * handling {@code null} by returning {@code true}.
- *
- *
- * BooleanUtils.isNotFalse(Boolean.TRUE) = true
- * BooleanUtils.isNotFalse(Boolean.FALSE) = false
- * BooleanUtils.isNotFalse(null) = true
- *
- *
- * @param bool the boolean to check, null returns {@code true}
- * @return {@code true} if the input is null or true
- * @since 2.3
- */
- public static boolean isNotFalse(final Boolean bool) {
- return !isFalse(bool);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts a Boolean to a boolean handling {@code null}
- * by returning {@code false}.
- *
- *
- * BooleanUtils.toBoolean(Boolean.TRUE) = true
- * BooleanUtils.toBoolean(Boolean.FALSE) = false
- * BooleanUtils.toBoolean(null) = false
- *
- *
- * @param bool the boolean to convert
- * @return {@code true} or {@code false}, {@code null} returns {@code false}
- */
- public static boolean toBoolean(final Boolean bool) {
- return bool != null && bool.booleanValue();
- }
-
- /**
- * Converts a Boolean to a boolean handling {@code null}.
- *
- *
- * BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, false) = true
- * BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, true) = false
- * BooleanUtils.toBooleanDefaultIfNull(null, true) = true
- *
- *
- * @param bool the boolean to convert
- * @param valueIfNull the boolean value to return if {@code null}
- * @return {@code true} or {@code false}
- */
- public static boolean toBooleanDefaultIfNull(final Boolean bool, final boolean valueIfNull) {
- if (bool == null) {
- return valueIfNull;
- }
- return bool.booleanValue();
- }
-
- // Integer to Boolean methods
- //-----------------------------------------------------------------------
- /**
- * Converts an int to a boolean using the convention that {@code zero}
- * is {@code false}.
- *
- *
- * BooleanUtils.toBoolean(0) = false
- * BooleanUtils.toBoolean(1) = true
- * BooleanUtils.toBoolean(2) = true
- *
- *
- * @param value the int to convert
- * @return {@code true} if non-zero, {@code false}
- * if zero
- */
- public static boolean toBoolean(final int value) {
- return value != 0;
- }
-
- /**
- * Converts an int to a Boolean using the convention that {@code zero}
- * is {@code false}.
- *
- *
- * BooleanUtils.toBoolean(0) = Boolean.FALSE
- * BooleanUtils.toBoolean(1) = Boolean.TRUE
- * BooleanUtils.toBoolean(2) = Boolean.TRUE
- *
- *
- * @param value the int to convert
- * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
- * {@code null} if {@code null}
- */
- public static Boolean toBooleanObject(final int value) {
- return value == 0 ? Boolean.FALSE : Boolean.TRUE;
- }
-
- /**
- * Converts an Integer to a Boolean using the convention that {@code zero}
- * is {@code false}.
- *
- * {@code null} will be converted to {@code null}.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * BooleanUtils.toBoolean(Integer.valueOf(0)) = Boolean.FALSE
- * BooleanUtils.toBoolean(Integer.valueOf(1)) = Boolean.TRUE
- * BooleanUtils.toBoolean(Integer.valueOf(null)) = null
- *
- *
- * @param value the Integer to convert
- * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
- * {@code null} if {@code null} input
- */
- public static Boolean toBooleanObject(final Integer value) {
- if (value == null) {
- return null;
- }
- return value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
- }
-
- /**
- * Converts an int to a boolean specifying the conversion values.
- *
- *
- * BooleanUtils.toBoolean(0, 1, 0) = false
- * BooleanUtils.toBoolean(1, 1, 0) = true
- * BooleanUtils.toBoolean(2, 1, 2) = false
- * BooleanUtils.toBoolean(2, 2, 0) = true
- *
- *
- * @param value the Integer to convert
- * @param trueValue the value to match for {@code true}
- * @param falseValue the value to match for {@code false}
- * @return {@code true} or {@code false}
- * @throws IllegalArgumentException if no match
- */
- public static boolean toBoolean(final int value, final int trueValue, final int falseValue) {
- if (value == trueValue) {
- return true;
- }
- if (value == falseValue) {
- return false;
- }
- // no match
- throw new IllegalArgumentException("The Integer did not match either specified value");
- }
-
- /**
- * Converts an Integer to a boolean specifying the conversion values.
- *
- *
- * BooleanUtils.toBoolean(Integer.valueOf(0), Integer.valueOf(1), Integer.valueOf(0)) = false
- * BooleanUtils.toBoolean(Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(0)) = true
- * BooleanUtils.toBoolean(Integer.valueOf(2), Integer.valueOf(1), Integer.valueOf(2)) = false
- * BooleanUtils.toBoolean(Integer.valueOf(2), Integer.valueOf(2), Integer.valueOf(0)) = true
- * BooleanUtils.toBoolean(null, null, Integer.valueOf(0)) = true
- *
- *
- * @param value the Integer to convert
- * @param trueValue the value to match for {@code true}, may be {@code null}
- * @param falseValue the value to match for {@code false}, may be {@code null}
- * @return {@code true} or {@code false}
- * @throws IllegalArgumentException if no match
- */
- public static boolean toBoolean(final Integer value, final Integer trueValue, final Integer falseValue) {
- if (value == null) {
- if (trueValue == null) {
- return true;
- }
- if (falseValue == null) {
- return false;
- }
- } else if (value.equals(trueValue)) {
- return true;
- } else if (value.equals(falseValue)) {
- return false;
- }
- // no match
- throw new IllegalArgumentException("The Integer did not match either specified value");
- }
-
- /**
- * Converts an int to a Boolean specifying the conversion values.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * BooleanUtils.toBooleanObject(0, 0, 2, 3) = Boolean.TRUE
- * BooleanUtils.toBooleanObject(2, 1, 2, 3) = Boolean.FALSE
- * BooleanUtils.toBooleanObject(3, 1, 2, 3) = null
- *
- *
- * @param value the Integer to convert
- * @param trueValue the value to match for {@code true}
- * @param falseValue the value to match for {@code false}
- * @param nullValue the value to to match for {@code null}
- * @return Boolean.TRUE, Boolean.FALSE, or {@code null}
- * @throws IllegalArgumentException if no match
- */
- public static Boolean toBooleanObject(final int value, final int trueValue, final int falseValue, final int nullValue) {
- if (value == trueValue) {
- return Boolean.TRUE;
- }
- if (value == falseValue) {
- return Boolean.FALSE;
- }
- if (value == nullValue) {
- return null;
- }
- // no match
- throw new IllegalArgumentException("The Integer did not match any specified value");
- }
-
- /**
- * Converts an Integer to a Boolean specifying the conversion values.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * BooleanUtils.toBooleanObject(Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(2), Integer.valueOf(3)) = Boolean.TRUE
- * BooleanUtils.toBooleanObject(Integer.valueOf(2), Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)) = Boolean.FALSE
- * BooleanUtils.toBooleanObject(Integer.valueOf(3), Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)) = null
- *
- *
- * @param value the Integer to convert
- * @param trueValue the value to match for {@code true}, may be {@code null}
- * @param falseValue the value to match for {@code false}, may be {@code null}
- * @param nullValue the value to to match for {@code null}, may be {@code null}
- * @return Boolean.TRUE, Boolean.FALSE, or {@code null}
- * @throws IllegalArgumentException if no match
- */
- public static Boolean toBooleanObject(final Integer value, final Integer trueValue, final Integer falseValue, final Integer nullValue) {
- if (value == null) {
- if (trueValue == null) {
- return Boolean.TRUE;
- }
- if (falseValue == null) {
- return Boolean.FALSE;
- }
- if (nullValue == null) {
- return null;
- }
- } else if (value.equals(trueValue)) {
- return Boolean.TRUE;
- } else if (value.equals(falseValue)) {
- return Boolean.FALSE;
- } else if (value.equals(nullValue)) {
- return null;
- }
- // no match
- throw new IllegalArgumentException("The Integer did not match any specified value");
- }
-
- // Boolean to Integer methods
- //-----------------------------------------------------------------------
- /**
- * Converts a boolean to an int using the convention that
- * {@code zero} is {@code false}.
- *
- *
- * BooleanUtils.toInteger(true) = 1
- * BooleanUtils.toInteger(false) = 0
- *
- *
- * @param bool the boolean to convert
- * @return one if {@code true}, zero if {@code false}
- */
- public static int toInteger(final boolean bool) {
- return bool ? 1 : 0;
- }
-
- /**
- * Converts a boolean to an Integer using the convention that
- * {@code zero} is {@code false}.
- *
- *
- * BooleanUtils.toIntegerObject(true) = Integer.valueOf(1)
- * BooleanUtils.toIntegerObject(false) = Integer.valueOf(0)
- *
- *
- * @param bool the boolean to convert
- * @return one if {@code true}, zero if {@code false}
- */
- public static Integer toIntegerObject(final boolean bool) {
- return bool ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
- }
-
- /**
- * Converts a Boolean to a Integer using the convention that
- * {@code zero} is {@code false}.
- *
- * {@code null} will be converted to {@code null}.
- *
- *
- * BooleanUtils.toIntegerObject(Boolean.TRUE) = Integer.valueOf(1)
- * BooleanUtils.toIntegerObject(Boolean.FALSE) = Integer.valueOf(0)
- *
- *
- * @param bool the Boolean to convert
- * @return one if Boolean.TRUE, zero if Boolean.FALSE, {@code null} if {@code null}
- */
- public static Integer toIntegerObject(final Boolean bool) {
- if (bool == null) {
- return null;
- }
- return bool.booleanValue() ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
- }
-
- /**
- * Converts a boolean to an int specifying the conversion values.
- *
- *
- * BooleanUtils.toInteger(true, 1, 0) = 1
- * BooleanUtils.toInteger(false, 1, 0) = 0
- *
- *
- * @param bool the to convert
- * @param trueValue the value to return if {@code true}
- * @param falseValue the value to return if {@code false}
- * @return the appropriate value
- */
- public static int toInteger(final boolean bool, final int trueValue, final int falseValue) {
- return bool ? trueValue : falseValue;
- }
-
- /**
- * Converts a Boolean to an int specifying the conversion values.
- *
- *
- * BooleanUtils.toInteger(Boolean.TRUE, 1, 0, 2) = 1
- * BooleanUtils.toInteger(Boolean.FALSE, 1, 0, 2) = 0
- * BooleanUtils.toInteger(null, 1, 0, 2) = 2
- *
- *
- * @param bool the Boolean to convert
- * @param trueValue the value to return if {@code true}
- * @param falseValue the value to return if {@code false}
- * @param nullValue the value to return if {@code null}
- * @return the appropriate value
- */
- public static int toInteger(final Boolean bool, final int trueValue, final int falseValue, final int nullValue) {
- if (bool == null) {
- return nullValue;
- }
- return bool.booleanValue() ? trueValue : falseValue;
- }
-
- /**
- * Converts a boolean to an Integer specifying the conversion values.
- *
- *
- * BooleanUtils.toIntegerObject(true, Integer.valueOf(1), Integer.valueOf(0)) = Integer.valueOf(1)
- * BooleanUtils.toIntegerObject(false, Integer.valueOf(1), Integer.valueOf(0)) = Integer.valueOf(0)
- *
- *
- * @param bool the to convert
- * @param trueValue the value to return if {@code true}, may be {@code null}
- * @param falseValue the value to return if {@code false}, may be {@code null}
- * @return the appropriate value
- */
- public static Integer toIntegerObject(final boolean bool, final Integer trueValue, final Integer falseValue) {
- return bool ? trueValue : falseValue;
- }
-
- /**
- * Converts a Boolean to an Integer specifying the conversion values.
- *
- *
- * BooleanUtils.toIntegerObject(Boolean.TRUE, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(1)
- * BooleanUtils.toIntegerObject(Boolean.FALSE, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(0)
- * BooleanUtils.toIntegerObject(null, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(2)
- *
- *
- * @param bool the Boolean to convert
- * @param trueValue the value to return if {@code true}, may be {@code null}
- * @param falseValue the value to return if {@code false}, may be {@code null}
- * @param nullValue the value to return if {@code null}, may be {@code null}
- * @return the appropriate value
- */
- public static Integer toIntegerObject(final Boolean bool, final Integer trueValue, final Integer falseValue, final Integer nullValue) {
- if (bool == null) {
- return nullValue;
- }
- return bool.booleanValue() ? trueValue : falseValue;
- }
-
- // String to Boolean methods
- //-----------------------------------------------------------------------
- /**
- * Converts a String to a Boolean.
- *
- * {@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
- * (case insensitive) will return {@code true}.
- * {@code 'false'}, {@code 'off'}, {@code 'n'}, {@code 'f'} or {@code 'no'}
- * (case insensitive) will return {@code false}.
- * Otherwise, {@code null} is returned.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * // N.B. case is not significant
- * BooleanUtils.toBooleanObject(null) = null
- * BooleanUtils.toBooleanObject("true") = Boolean.TRUE
- * BooleanUtils.toBooleanObject("T") = Boolean.TRUE // i.e. T[RUE]
- * BooleanUtils.toBooleanObject("false") = Boolean.FALSE
- * BooleanUtils.toBooleanObject("f") = Boolean.FALSE // i.e. f[alse]
- * BooleanUtils.toBooleanObject("No") = Boolean.FALSE
- * BooleanUtils.toBooleanObject("n") = Boolean.FALSE // i.e. n[o]
- * BooleanUtils.toBooleanObject("on") = Boolean.TRUE
- * BooleanUtils.toBooleanObject("ON") = Boolean.TRUE
- * BooleanUtils.toBooleanObject("off") = Boolean.FALSE
- * BooleanUtils.toBooleanObject("oFf") = Boolean.FALSE
- * BooleanUtils.toBooleanObject("yes") = Boolean.TRUE
- * BooleanUtils.toBooleanObject("Y") = Boolean.TRUE // i.e. Y[ES]
- * BooleanUtils.toBooleanObject("blue") = null
- * BooleanUtils.toBooleanObject("true ") = null // trailing space (too long)
- * BooleanUtils.toBooleanObject("ono") = null // does not match on or no
- *
- *
- * @param str the String to check; upper and lower case are treated as the same
- * @return the Boolean value of the string, {@code null} if no match or {@code null} input
- */
- public static Boolean toBooleanObject(final String str) {
- // Previously used equalsIgnoreCase, which was fast for interned 'true'.
- // Non interned 'true' matched 15 times slower.
- //
- // Optimisation provides same performance as before for interned 'true'.
- // Similar performance for null, 'false', and other strings not length 2/3/4.
- // 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
- if (str == "true") {
- return Boolean.TRUE;
- }
- if (str == null) {
- return null;
- }
- switch (str.length()) {
- case 1: {
- final char ch0 = str.charAt(0);
- if (ch0 == 'y' || ch0 == 'Y' ||
- ch0 == 't' || ch0 == 'T') {
- return Boolean.TRUE;
- }
- if (ch0 == 'n' || ch0 == 'N' ||
- ch0 == 'f' || ch0 == 'F') {
- return Boolean.FALSE;
- }
- break;
- }
- case 2: {
- final char ch0 = str.charAt(0);
- final char ch1 = str.charAt(1);
- if ((ch0 == 'o' || ch0 == 'O') &&
- (ch1 == 'n' || ch1 == 'N') ) {
- return Boolean.TRUE;
- }
- if ((ch0 == 'n' || ch0 == 'N') &&
- (ch1 == 'o' || ch1 == 'O') ) {
- return Boolean.FALSE;
- }
- break;
- }
- case 3: {
- final char ch0 = str.charAt(0);
- final char ch1 = str.charAt(1);
- final char ch2 = str.charAt(2);
- if ((ch0 == 'y' || ch0 == 'Y') &&
- (ch1 == 'e' || ch1 == 'E') &&
- (ch2 == 's' || ch2 == 'S') ) {
- return Boolean.TRUE;
- }
- if ((ch0 == 'o' || ch0 == 'O') &&
- (ch1 == 'f' || ch1 == 'F') &&
- (ch2 == 'f' || ch2 == 'F') ) {
- return Boolean.FALSE;
- }
- break;
- }
- case 4: {
- final char ch0 = str.charAt(0);
- final char ch1 = str.charAt(1);
- final char ch2 = str.charAt(2);
- final char ch3 = str.charAt(3);
- if ((ch0 == 't' || ch0 == 'T') &&
- (ch1 == 'r' || ch1 == 'R') &&
- (ch2 == 'u' || ch2 == 'U') &&
- (ch3 == 'e' || ch3 == 'E') ) {
- return Boolean.TRUE;
- }
- break;
- }
- case 5: {
- final char ch0 = str.charAt(0);
- final char ch1 = str.charAt(1);
- final char ch2 = str.charAt(2);
- final char ch3 = str.charAt(3);
- final char ch4 = str.charAt(4);
- if ((ch0 == 'f' || ch0 == 'F') &&
- (ch1 == 'a' || ch1 == 'A') &&
- (ch2 == 'l' || ch2 == 'L') &&
- (ch3 == 's' || ch3 == 'S') &&
- (ch4 == 'e' || ch4 == 'E') ) {
- return Boolean.FALSE;
- }
- break;
- }
- default:
- break;
- }
-
- return null;
- }
-
- /**
- * Converts a String to a Boolean throwing an exception if no match.
- *
- * NOTE: This returns null and will throw a NullPointerException if unboxed to a boolean.
- *
- *
- * BooleanUtils.toBooleanObject("true", "true", "false", "null") = Boolean.TRUE
- * BooleanUtils.toBooleanObject("false", "true", "false", "null") = Boolean.FALSE
- * BooleanUtils.toBooleanObject("null", "true", "false", "null") = null
- *
- *
- * @param str the String to check
- * @param trueString the String to match for {@code true} (case sensitive), may be {@code null}
- * @param falseString the String to match for {@code false} (case sensitive), may be {@code null}
- * @param nullString the String to match for {@code null} (case sensitive), may be {@code null}
- * @return the Boolean value of the string, {@code null} if either the String matches {@code nullString}
- * or if {@code null} input and {@code nullString} is {@code null}
- * @throws IllegalArgumentException if the String doesn't match
- */
- public static Boolean toBooleanObject(final String str, final String trueString, final String falseString, final String nullString) {
- if (str == null) {
- if (trueString == null) {
- return Boolean.TRUE;
- }
- if (falseString == null) {
- return Boolean.FALSE;
- }
- if (nullString == null) {
- return null;
- }
- } else if (str.equals(trueString)) {
- return Boolean.TRUE;
- } else if (str.equals(falseString)) {
- return Boolean.FALSE;
- } else if (str.equals(nullString)) {
- return null;
- }
- // no match
- throw new IllegalArgumentException("The String did not match any specified value");
- }
-
- // String to boolean methods
- //-----------------------------------------------------------------------
- /**
- * Converts a String to a boolean (optimised for performance).
- *
- * {@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
- * (case insensitive) will return {@code true}. Otherwise,
- * {@code false} is returned.
- *
- * This method performs 4 times faster (JDK1.4) than
- * {@code Boolean.valueOf(String)}. However, this method accepts
- * 'on' and 'yes', 't', 'y' as true values.
- *
- *
- * BooleanUtils.toBoolean(null) = false
- * BooleanUtils.toBoolean("true") = true
- * BooleanUtils.toBoolean("TRUE") = true
- * BooleanUtils.toBoolean("tRUe") = true
- * BooleanUtils.toBoolean("on") = true
- * BooleanUtils.toBoolean("yes") = true
- * BooleanUtils.toBoolean("false") = false
- * BooleanUtils.toBoolean("x gti") = false
- * BooleanUtils.toBooleanObject("y") = true
- * BooleanUtils.toBooleanObject("n") = false
- * BooleanUtils.toBooleanObject("t") = true
- * BooleanUtils.toBooleanObject("f") = false
- *
- *
- * @param str the String to check
- * @return the boolean value of the string, {@code false} if no match or the String is null
- */
- public static boolean toBoolean(final String str) {
- return toBooleanObject(str) == Boolean.TRUE;
- }
-
- /**
- * Converts a String to a Boolean throwing an exception if no match found.
- *
- *
- * BooleanUtils.toBoolean("true", "true", "false") = true
- * BooleanUtils.toBoolean("false", "true", "false") = false
- *
- *
- * @param str the String to check
- * @param trueString the String to match for {@code true} (case sensitive), may be {@code null}
- * @param falseString the String to match for {@code false} (case sensitive), may be {@code null}
- * @return the boolean value of the string
- * @throws IllegalArgumentException if the String doesn't match
- */
- public static boolean toBoolean(final String str, final String trueString, final String falseString) {
- if (str == trueString) {
- return true;
- } else if (str == falseString) {
- return false;
- } else if (str != null) {
- if (str.equals(trueString)) {
- return true;
- } else if (str.equals(falseString)) {
- return false;
- }
- }
- // no match
- throw new IllegalArgumentException("The String did not match either specified value");
- }
-
- // Boolean to String methods
- //-----------------------------------------------------------------------
- /**
- * Converts a Boolean to a String returning {@code 'true'},
- * {@code 'false'}, or {@code null}.
- *
- *
- * BooleanUtils.toStringTrueFalse(Boolean.TRUE) = "true"
- * BooleanUtils.toStringTrueFalse(Boolean.FALSE) = "false"
- * BooleanUtils.toStringTrueFalse(null) = null;
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'true'}, {@code 'false'}, or {@code null}
- */
- public static String toStringTrueFalse(final Boolean bool) {
- return toString(bool, "true", "false", null);
- }
-
- /**
- * Converts a Boolean to a String returning {@code 'on'},
- * {@code 'off'}, or {@code null}.
- *
- *
- * BooleanUtils.toStringOnOff(Boolean.TRUE) = "on"
- * BooleanUtils.toStringOnOff(Boolean.FALSE) = "off"
- * BooleanUtils.toStringOnOff(null) = null;
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'on'}, {@code 'off'}, or {@code null}
- */
- public static String toStringOnOff(final Boolean bool) {
- return toString(bool, "on", "off", null);
- }
-
- /**
- * Converts a Boolean to a String returning {@code 'yes'},
- * {@code 'no'}, or {@code null}.
- *
- *
- * BooleanUtils.toStringYesNo(Boolean.TRUE) = "yes"
- * BooleanUtils.toStringYesNo(Boolean.FALSE) = "no"
- * BooleanUtils.toStringYesNo(null) = null;
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'yes'}, {@code 'no'}, or {@code null}
- */
- public static String toStringYesNo(final Boolean bool) {
- return toString(bool, "yes", "no", null);
- }
-
- /**
- * Converts a Boolean to a String returning one of the input Strings.
- *
- *
- * BooleanUtils.toString(Boolean.TRUE, "true", "false", null) = "true"
- * BooleanUtils.toString(Boolean.FALSE, "true", "false", null) = "false"
- * BooleanUtils.toString(null, "true", "false", null) = null;
- *
- *
- * @param bool the Boolean to check
- * @param trueString the String to return if {@code true}, may be {@code null}
- * @param falseString the String to return if {@code false}, may be {@code null}
- * @param nullString the String to return if {@code null}, may be {@code null}
- * @return one of the three input Strings
- */
- public static String toString(final Boolean bool, final String trueString, final String falseString, final String nullString) {
- if (bool == null) {
- return nullString;
- }
- return bool.booleanValue() ? trueString : falseString;
- }
-
- // boolean to String methods
- //-----------------------------------------------------------------------
- /**
- * Converts a boolean to a String returning {@code 'true'}
- * or {@code 'false'}.
- *
- *
- * BooleanUtils.toStringTrueFalse(true) = "true"
- * BooleanUtils.toStringTrueFalse(false) = "false"
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'true'}, {@code 'false'}, or {@code null}
- */
- public static String toStringTrueFalse(final boolean bool) {
- return toString(bool, "true", "false");
- }
-
- /**
- * Converts a boolean to a String returning {@code 'on'}
- * or {@code 'off'}.
- *
- *
- * BooleanUtils.toStringOnOff(true) = "on"
- * BooleanUtils.toStringOnOff(false) = "off"
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'on'}, {@code 'off'}, or {@code null}
- */
- public static String toStringOnOff(final boolean bool) {
- return toString(bool, "on", "off");
- }
-
- /**
- * Converts a boolean to a String returning {@code 'yes'}
- * or {@code 'no'}.
- *
- *
- * BooleanUtils.toStringYesNo(true) = "yes"
- * BooleanUtils.toStringYesNo(false) = "no"
- *
- *
- * @param bool the Boolean to check
- * @return {@code 'yes'}, {@code 'no'}, or {@code null}
- */
- public static String toStringYesNo(final boolean bool) {
- return toString(bool, "yes", "no");
- }
-
- /**
- * Converts a boolean to a String returning one of the input Strings.
- *
- *
- * BooleanUtils.toString(true, "true", "false") = "true"
- * BooleanUtils.toString(false, "true", "false") = "false"
- *
- *
- * @param bool the Boolean to check
- * @param trueString the String to return if {@code true}, may be {@code null}
- * @param falseString the String to return if {@code false}, may be {@code null}
- * @return one of the two input Strings
- */
- public static String toString(final boolean bool, final String trueString, final String falseString) {
- return bool ? trueString : falseString;
- }
-
- // logical operations
- // ----------------------------------------------------------------------
- /**
- * Performs an and on a set of booleans.
- *
- *
- * BooleanUtils.and(true, true) = true
- * BooleanUtils.and(false, false) = false
- * BooleanUtils.and(true, false) = false
- * BooleanUtils.and(true, true, false) = false
- * BooleanUtils.and(true, true, true) = true
- *
- *
- * @param array an array of {@code boolean}s
- * @return {@code true} if the and is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- * @since 3.0.1
- */
- public static boolean and(final boolean... array) {
- // Validates input
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
- for (final boolean element : array) {
- if (!element) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Performs an and on an array of Booleans.
- *
- *
- * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
- * BooleanUtils.and(Boolean.TRUE, Boolean.FALSE) = Boolean.FALSE
- * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
- * BooleanUtils.and(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
- *
- *
- * @param array an array of {@code Boolean}s
- * @return {@code true} if the and is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- * @throws IllegalArgumentException if {@code array} contains a {@code null}
- * @since 3.0.1
- */
- public static Boolean and(final Boolean... array) {
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
- try {
- final boolean[] primitive = ArrayUtils.toPrimitive(array);
- return and(primitive) ? Boolean.TRUE : Boolean.FALSE;
- } catch (final NullPointerException ex) {
- throw new IllegalArgumentException("The array must not contain any null elements");
- }
- }
-
- /**
- * Performs an or on a set of booleans.
- *
- *
- * BooleanUtils.or(true, true) = true
- * BooleanUtils.or(false, false) = false
- * BooleanUtils.or(true, false) = true
- * BooleanUtils.or(true, true, false) = true
- * BooleanUtils.or(true, true, true) = true
- * BooleanUtils.or(false, false, false) = false
- *
- *
- * @param array an array of {@code boolean}s
- * @return {@code true} if the or is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- * @since 3.0.1
- */
- public static boolean or(final boolean... array) {
- // Validates input
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
- for (final boolean element : array) {
- if (element) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Performs an or on an array of Booleans.
- *
- *
- * BooleanUtils.or(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
- * BooleanUtils.or(Boolean.TRUE, Boolean.FALSE) = Boolean.TRUE
- * BooleanUtils.or(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
- * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
- *
- *
- * @param array an array of {@code Boolean}s
- * @return {@code true} if the or is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- * @throws IllegalArgumentException if {@code array} contains a {@code null}
- * @since 3.0.1
- */
- public static Boolean or(final Boolean... array) {
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
- try {
- final boolean[] primitive = ArrayUtils.toPrimitive(array);
- return or(primitive) ? Boolean.TRUE : Boolean.FALSE;
- } catch (final NullPointerException ex) {
- throw new IllegalArgumentException("The array must not contain any null elements");
- }
- }
-
- /**
- * Performs an xor on a set of booleans.
- *
- *
- * BooleanUtils.xor(true, true) = false
- * BooleanUtils.xor(false, false) = false
- * BooleanUtils.xor(true, false) = true
- *
- *
- * @param array an array of {@code boolean}s
- * @return {@code true} if the xor is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- */
- public static boolean xor(final boolean... array) {
- // Validates input
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
-
- // false if the neutral element of the xor operator
- boolean result = false;
- for (final boolean element : array) {
- result ^= element;
- }
-
- return result;
- }
-
- /**
- * Performs an xor on an array of Booleans.
- *
- *
- * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE }) = Boolean.FALSE
- * BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE
- * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }) = Boolean.TRUE
- *
- *
- * @param array an array of {@code Boolean}s
- * @return {@code true} if the xor is successful.
- * @throws IllegalArgumentException if {@code array} is {@code null}
- * @throws IllegalArgumentException if {@code array} is empty.
- * @throws IllegalArgumentException if {@code array} contains a {@code null}
- */
- public static Boolean xor(final Boolean... array) {
- if (array == null) {
- throw new IllegalArgumentException("The Array must not be null");
- }
- if (array.length == 0) {
- throw new IllegalArgumentException("Array is empty");
- }
- try {
- final boolean[] primitive = ArrayUtils.toPrimitive(array);
- return xor(primitive) ? Boolean.TRUE : Boolean.FALSE;
- } catch (final NullPointerException ex) {
- throw new IllegalArgumentException("The array must not contain any null elements");
- }
- }
-
- /**
- * Compares two {@code boolean} values. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code boolean} to compare
- * @param y the second {@code boolean} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code !x && y}; and
- * a value greater than {@code 0} if {@code x && !y}
- * @since 3.4
- */
- public static int compare(final boolean x, final boolean y) {
- if (x == y) {
- return 0;
- }
- return x ? 1 : -1;
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Builder.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Builder.java
deleted file mode 100644
index 6da65c8c..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Builder.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-/**
- *
- * The Builder interface is designed to designate a class as a builder
- * object in the Builder design pattern. Builders are capable of creating and
- * configuring objects or results that normally take multiple steps to construct
- * or are very complex to derive.
- *
- *
- *
- * The builder interface defines a single method, {@link #build()}, that
- * classes must implement. The result of this method should be the final
- * configured object or result after all building operations are performed.
- *
- *
- *
- * It is a recommended practice that the methods supplied to configure the
- * object or result being built return a reference to {@code this} so that
- * method calls can be chained together.
- *
- *
- *
- * Example Builder:
- *
- * class FontBuilder implements Builder<Font> {
- * private Font font;
- *
- * public FontBuilder(String fontName) {
- * this.font = new Font(fontName, Font.PLAIN, 12);
- * }
- *
- * public FontBuilder bold() {
- * this.font = this.font.deriveFont(Font.BOLD);
- * return this; // Reference returned so calls can be chained
- * }
- *
- * public FontBuilder size(float pointSize) {
- * this.font = this.font.deriveFont(pointSize);
- * return this; // Reference returned so calls can be chained
- * }
- *
- * // Other Font construction methods
- *
- * public Font build() {
- * return this.font;
- * }
- * }
- *
- *
- * Example Builder Usage:
- *
- * Font bold14ptSansSerifFont = new FontBuilder(Font.SANS_SERIF).bold()
- * .size(14.0f)
- * .build();
- *
- *
- *
- * @param the type of object that the builder will construct or compute.
- *
- * @since 3.0
- */
-public interface Builder {
-
- /**
- * Returns a reference to the object being constructed or result being
- * calculated by the builder.
- *
- * @return the object constructed or result calculated by the builder.
- */
- T build();
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharSequenceUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharSequenceUtils.java
deleted file mode 100644
index 9cb955fa..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharSequenceUtils.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-/**
- * Operations on {@link CharSequence} that are
- * {@code null} safe.
- *
- * @see CharSequence
- * @since 3.0
- */
-public class CharSequenceUtils {
-
- private static final int NOT_FOUND = -1;
-
- /**
- * {@code CharSequenceUtils} instances should NOT be constructed in
- * standard programming.
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
- */
- public CharSequenceUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns a new {@code CharSequence} that is a subsequence of this
- * sequence starting with the {@code char} value at the specified index.
- *
- * This provides the {@code CharSequence} equivalent to {@link String#substring(int)}.
- * The length (in {@code char}) of the returned sequence is {@code length() - start},
- * so if {@code start == end} then an empty sequence is returned.
- *
- * @param cs the specified subsequence, null returns null
- * @param start the start index, inclusive, valid
- * @return a new subsequence, may be null
- * @throws IndexOutOfBoundsException if {@code start} is negative or if
- * {@code start} is greater than {@code length()}
- */
- public static CharSequence subSequence(final CharSequence cs, final int start) {
- return cs == null ? null : cs.subSequence(start, cs.length());
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the index within cs of the first occurrence of the
- * specified character, starting the search at the specified index.
- *
- * If a character with value searchChar occurs in the
- * character sequence represented by the cs
- * object at an index no smaller than start, then
- * the index of the first such occurrence is returned. For values
- * of searchChar in the range from 0 to 0xFFFF (inclusive),
- * this is the smallest value k such that:
- *
- * (this.charAt(k ) == searchChar) && (k >= start)
- *
- * is true. For other values of searchChar, it is the
- * smallest value k such that:
- *
- * (this.codePointAt(k ) == searchChar) && (k >= start)
- *
- * is true. In either case, if no such character occurs inm cs
- * at or after position start, then
- * -1 is returned.
- *
- *
- * There is no restriction on the value of start. If it
- * is negative, it has the same effect as if it were zero: the entire
- * CharSequence may be searched. If it is greater than
- * the length of cs, it has the same effect as if it were
- * equal to the length of cs: -1 is returned.
- *
- *
All indices are specified in char values
- * (Unicode code units).
- *
- * @param cs the {@code CharSequence} to be processed, not null
- * @param searchChar the char to be searched for
- * @param start the start index, negative starts at the string start
- * @return the index where the search char was found, -1 if not found
- * @since 3.6 updated to behave more like String
- */
- static int indexOf(final CharSequence cs, final int searchChar, int start) {
- if (cs instanceof String) {
- return ((String) cs).indexOf(searchChar, start);
- }
- final int sz = cs.length();
- if (start < 0) {
- start = 0;
- }
- if (searchChar < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- for (int i = start; i < sz; i++) {
- if (cs.charAt(i) == searchChar) {
- return i;
- }
- }
- }
- //supplementary characters (LANG1300)
- if (searchChar <= Character.MAX_CODE_POINT) {
- final char[] chars = Character.toChars(searchChar);
- for (int i = start; i < sz - 1; i++) {
- final char high = cs.charAt(i);
- final char low = cs.charAt(i + 1);
- if (high == chars[0] && low == chars[1]) {
- return i;
- }
- }
- }
- return NOT_FOUND;
- }
-
- /**
- * Used by the indexOf(CharSequence methods) as a green implementation of indexOf.
- *
- * @param cs the {@code CharSequence} to be processed
- * @param searchChar the {@code CharSequence} to be searched for
- * @param start the start index
- * @return the index where the search sequence was found
- */
- static int indexOf(final CharSequence cs, final CharSequence searchChar, final int start) {
- return cs.toString().indexOf(searchChar.toString(), start);
-// if (cs instanceof String && searchChar instanceof String) {
-// // TODO: Do we assume searchChar is usually relatively small;
-// // If so then calling toString() on it is better than reverting to
-// // the green implementation in the else block
-// return ((String) cs).indexOf((String) searchChar, start);
-// } else {
-// // TODO: Implement rather than convert to String
-// return cs.toString().indexOf(searchChar.toString(), start);
-// }
- }
-
- /**
- * Returns the index within cs of the last occurrence of
- * the specified character, searching backward starting at the
- * specified index. For values of searchChar in the range
- * from 0 to 0xFFFF (inclusive), the index returned is the largest
- * value k such that:
- *
- * (this.charAt(k ) == searchChar) && (k <= start)
- *
- * is true. For other values of searchChar, it is the
- * largest value k such that:
- *
- * (this.codePointAt(k ) == searchChar) && (k <= start)
- *
- * is true. In either case, if no such character occurs in cs
- * at or before position start, then -1 is returned.
- *
- * All indices are specified in char values
- * (Unicode code units).
- *
- * @param cs the {@code CharSequence} to be processed
- * @param searchChar the char to be searched for
- * @param start the start index, negative returns -1, beyond length starts at end
- * @return the index where the search char was found, -1 if not found
- * @since 3.6 updated to behave more like String
- */
- static int lastIndexOf(final CharSequence cs, final int searchChar, int start) {
- if (cs instanceof String) {
- return ((String) cs).lastIndexOf(searchChar, start);
- }
- final int sz = cs.length();
- if (start < 0) {
- return NOT_FOUND;
- }
- if (start >= sz) {
- start = sz - 1;
- }
- if (searchChar < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- for (int i = start; i >= 0; --i) {
- if (cs.charAt(i) == searchChar) {
- return i;
- }
- }
- }
- //supplementary characters (LANG1300)
- //NOTE - we must do a forward traversal for this to avoid duplicating code points
- if (searchChar <= Character.MAX_CODE_POINT) {
- final char[] chars = Character.toChars(searchChar);
- //make sure it's not the last index
- if (start == sz - 1) {
- return NOT_FOUND;
- }
- for (int i = start; i >= 0; i--) {
- final char high = cs.charAt(i);
- final char low = cs.charAt(i + 1);
- if (chars[0] == high && chars[1] == low) {
- return i;
- }
- }
- }
- return NOT_FOUND;
- }
-
- /**
- * Used by the lastIndexOf(CharSequence methods) as a green implementation of lastIndexOf
- *
- * @param cs the {@code CharSequence} to be processed
- * @param searchChar the {@code CharSequence} to be searched for
- * @param start the start index
- * @return the index where the search sequence was found
- */
- static int lastIndexOf(final CharSequence cs, final CharSequence searchChar, final int start) {
- return cs.toString().lastIndexOf(searchChar.toString(), start);
-// if (cs instanceof String && searchChar instanceof String) {
-// // TODO: Do we assume searchChar is usually relatively small;
-// // If so then calling toString() on it is better than reverting to
-// // the green implementation in the else block
-// return ((String) cs).lastIndexOf((String) searchChar, start);
-// } else {
-// // TODO: Implement rather than convert to String
-// return cs.toString().lastIndexOf(searchChar.toString(), start);
-// }
- }
-
- /**
- * Green implementation of toCharArray.
- *
- * @param cs the {@code CharSequence} to be processed
- * @return the resulting char array
- */
- static char[] toCharArray(final CharSequence cs) {
- if (cs instanceof String) {
- return ((String) cs).toCharArray();
- }
- final int sz = cs.length();
- final char[] array = new char[cs.length()];
- for (int i = 0; i < sz; i++) {
- array[i] = cs.charAt(i);
- }
- return array;
- }
-
- /**
- * Green implementation of regionMatches.
- *
- * @param cs the {@code CharSequence} to be processed
- * @param ignoreCase whether or not to be case insensitive
- * @param thisStart the index to start on the {@code cs} CharSequence
- * @param substring the {@code CharSequence} to be looked for
- * @param start the index to start on the {@code substring} CharSequence
- * @param length character length of the region
- * @return whether the region matched
- */
- static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
- final CharSequence substring, final int start, final int length) {
- if (cs instanceof String && substring instanceof String) {
- return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
- }
- int index1 = thisStart;
- int index2 = start;
- int tmpLen = length;
-
- // Extract these first so we detect NPEs the same as the java.lang.String version
- final int srcLen = cs.length() - thisStart;
- final int otherLen = substring.length() - start;
-
- // Check for invalid parameters
- if (thisStart < 0 || start < 0 || length < 0) {
- return false;
- }
-
- // Check that the regions are long enough
- if (srcLen < length || otherLen < length) {
- return false;
- }
-
- while (tmpLen-- > 0) {
- final char c1 = cs.charAt(index1++);
- final char c2 = substring.charAt(index2++);
-
- if (c1 == c2) {
- continue;
- }
-
- if (!ignoreCase) {
- return false;
- }
-
- // The same check as in String.regionMatches():
- if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
- && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharUtils.java
deleted file mode 100644
index 2ef98d7f..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/CharUtils.java
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-/**
- *
Operations on char primitives and Character objects.
- *
- * This class tries to handle {@code null} input gracefully.
- * An exception will not be thrown for a {@code null} input.
- * Each method documents its behaviour in more detail.
- *
- * #ThreadSafe#
- * @since 2.1
- */
-public class CharUtils {
-
- private static final String[] CHAR_STRING_ARRAY = new String[128];
-
- private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- /**
- * {@code \u000a} linefeed LF ('\n').
- *
- * @see JLF: Escape Sequences
- * for Character and String Literals
- * @since 2.2
- */
- public static final char LF = '\n';
-
- /**
- * {@code \u000d} carriage return CR ('\r').
- *
- * @see JLF: Escape Sequences
- * for Character and String Literals
- * @since 2.2
- */
- public static final char CR = '\r';
-
- /**
- * {@code \u0000} null control character ('\0'), abbreviated NUL.
- *
- * @since 3.6
- */
- public static final char NUL = '\0';
-
- static {
- for (char c = 0; c < CHAR_STRING_ARRAY.length; c++) {
- CHAR_STRING_ARRAY[c] = String.valueOf(c);
- }
- }
-
- /**
- * {@code CharUtils} instances should NOT be constructed in standard programming.
- * Instead, the class should be used as {@code CharUtils.toString('c');}.
- *
- * This constructor is public to permit tools that require a JavaBean instance
- * to operate.
- */
- public CharUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts the character to a Character.
- *
- * For ASCII 7 bit characters, this uses a cache that will return the
- * same Character object each time.
- *
- *
- * CharUtils.toCharacterObject(' ') = ' '
- * CharUtils.toCharacterObject('A') = 'A'
- *
- *
- * @deprecated Java 5 introduced {@link Character#valueOf(char)} which caches chars 0 through 127.
- * @param ch the character to convert
- * @return a Character of the specified character
- */
- @Deprecated
- public static Character toCharacterObject(final char ch) {
- return Character.valueOf(ch);
- }
-
- /**
- * Converts the String to a Character using the first character, returning
- * null for empty Strings.
- *
- * For ASCII 7 bit characters, this uses a cache that will return the
- * same Character object each time.
- *
- *
- * CharUtils.toCharacterObject(null) = null
- * CharUtils.toCharacterObject("") = null
- * CharUtils.toCharacterObject("A") = 'A'
- * CharUtils.toCharacterObject("BA") = 'B'
- *
- *
- * @param str the character to convert
- * @return the Character value of the first letter of the String
- */
- public static Character toCharacterObject(final String str) {
- if (StringUtils.isEmpty(str)) {
- return null;
- }
- return Character.valueOf(str.charAt(0));
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts the Character to a char throwing an exception for {@code null}.
- *
- *
- * CharUtils.toChar(' ') = ' '
- * CharUtils.toChar('A') = 'A'
- * CharUtils.toChar(null) throws IllegalArgumentException
- *
- *
- * @param ch the character to convert
- * @return the char value of the Character
- * @throws IllegalArgumentException if the Character is null
- */
- public static char toChar(final Character ch) {
- Validate.isTrue(ch != null, "The Character must not be null");
- return ch.charValue();
- }
-
- /**
- * Converts the Character to a char handling {@code null}.
- *
- *
- * CharUtils.toChar(null, 'X') = 'X'
- * CharUtils.toChar(' ', 'X') = ' '
- * CharUtils.toChar('A', 'X') = 'A'
- *
- *
- * @param ch the character to convert
- * @param defaultValue the value to use if the Character is null
- * @return the char value of the Character or the default if null
- */
- public static char toChar(final Character ch, final char defaultValue) {
- if (ch == null) {
- return defaultValue;
- }
- return ch.charValue();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts the String to a char using the first character, throwing
- * an exception on empty Strings.
- *
- *
- * CharUtils.toChar("A") = 'A'
- * CharUtils.toChar("BA") = 'B'
- * CharUtils.toChar(null) throws IllegalArgumentException
- * CharUtils.toChar("") throws IllegalArgumentException
- *
- *
- * @param str the character to convert
- * @return the char value of the first letter of the String
- * @throws IllegalArgumentException if the String is empty
- */
- public static char toChar(final String str) {
- Validate.isTrue(StringUtils.isNotEmpty(str), "The String must not be empty");
- return str.charAt(0);
- }
-
- /**
- * Converts the String to a char using the first character, defaulting
- * the value on empty Strings.
- *
- *
- * CharUtils.toChar(null, 'X') = 'X'
- * CharUtils.toChar("", 'X') = 'X'
- * CharUtils.toChar("A", 'X') = 'A'
- * CharUtils.toChar("BA", 'X') = 'B'
- *
- *
- * @param str the character to convert
- * @param defaultValue the value to use if the Character is null
- * @return the char value of the first letter of the String or the default if null
- */
- public static char toChar(final String str, final char defaultValue) {
- if (StringUtils.isEmpty(str)) {
- return defaultValue;
- }
- return str.charAt(0);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts the character to the Integer it represents, throwing an
- * exception if the character is not numeric.
- *
- * This method converts the char '1' to the int 1 and so on.
- *
- *
- * CharUtils.toIntValue('3') = 3
- * CharUtils.toIntValue('A') throws IllegalArgumentException
- *
- *
- * @param ch the character to convert
- * @return the int value of the character
- * @throws IllegalArgumentException if the character is not ASCII numeric
- */
- public static int toIntValue(final char ch) {
- if (!isAsciiNumeric(ch)) {
- throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
- }
- return ch - 48;
- }
-
- /**
- * Converts the character to the Integer it represents, throwing an
- * exception if the character is not numeric.
- *
- * This method converts the char '1' to the int 1 and so on.
- *
- *
- * CharUtils.toIntValue('3', -1) = 3
- * CharUtils.toIntValue('A', -1) = -1
- *
- *
- * @param ch the character to convert
- * @param defaultValue the default value to use if the character is not numeric
- * @return the int value of the character
- */
- public static int toIntValue(final char ch, final int defaultValue) {
- if (!isAsciiNumeric(ch)) {
- return defaultValue;
- }
- return ch - 48;
- }
-
- /**
- * Converts the character to the Integer it represents, throwing an
- * exception if the character is not numeric.
- *
- * This method converts the char '1' to the int 1 and so on.
- *
- *
- * CharUtils.toIntValue('3') = 3
- * CharUtils.toIntValue(null) throws IllegalArgumentException
- * CharUtils.toIntValue('A') throws IllegalArgumentException
- *
- *
- * @param ch the character to convert, not null
- * @return the int value of the character
- * @throws IllegalArgumentException if the Character is not ASCII numeric or is null
- */
- public static int toIntValue(final Character ch) {
- Validate.isTrue(ch != null, "The character must not be null");
- return toIntValue(ch.charValue());
- }
-
- /**
- * Converts the character to the Integer it represents, throwing an
- * exception if the character is not numeric.
- *
- * This method converts the char '1' to the int 1 and so on.
- *
- *
- * CharUtils.toIntValue(null, -1) = -1
- * CharUtils.toIntValue('3', -1) = 3
- * CharUtils.toIntValue('A', -1) = -1
- *
- *
- * @param ch the character to convert
- * @param defaultValue the default value to use if the character is not numeric
- * @return the int value of the character
- */
- public static int toIntValue(final Character ch, final int defaultValue) {
- if (ch == null) {
- return defaultValue;
- }
- return toIntValue(ch.charValue(), defaultValue);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Converts the character to a String that contains the one character.
- *
- * For ASCII 7 bit characters, this uses a cache that will return the
- * same String object each time.
- *
- *
- * CharUtils.toString(' ') = " "
- * CharUtils.toString('A') = "A"
- *
- *
- * @param ch the character to convert
- * @return a String containing the one specified character
- */
- public static String toString(final char ch) {
- if (ch < 128) {
- return CHAR_STRING_ARRAY[ch];
- }
- return new String(new char[] {ch});
- }
-
- /**
- * Converts the character to a String that contains the one character.
- *
- * For ASCII 7 bit characters, this uses a cache that will return the
- * same String object each time.
- *
- * If {@code null} is passed in, {@code null} will be returned.
- *
- *
- * CharUtils.toString(null) = null
- * CharUtils.toString(' ') = " "
- * CharUtils.toString('A') = "A"
- *
- *
- * @param ch the character to convert
- * @return a String containing the one specified character
- */
- public static String toString(final Character ch) {
- if (ch == null) {
- return null;
- }
- return toString(ch.charValue());
- }
-
- //--------------------------------------------------------------------------
- /**
- * Converts the string to the Unicode format '\u0020'.
- *
- * This format is the Java source code format.
- *
- *
- * CharUtils.unicodeEscaped(' ') = "\u0020"
- * CharUtils.unicodeEscaped('A') = "\u0041"
- *
- *
- * @param ch the character to convert
- * @return the escaped Unicode string
- */
- public static String unicodeEscaped(final char ch) {
- return "\\u" +
- HEX_DIGITS[(ch >> 12) & 15] +
- HEX_DIGITS[(ch >> 8) & 15] +
- HEX_DIGITS[(ch >> 4) & 15] +
- HEX_DIGITS[(ch) & 15];
- }
-
- /**
- * Converts the string to the Unicode format '\u0020'.
- *
- * This format is the Java source code format.
- *
- * If {@code null} is passed in, {@code null} will be returned.
- *
- *
- * CharUtils.unicodeEscaped(null) = null
- * CharUtils.unicodeEscaped(' ') = "\u0020"
- * CharUtils.unicodeEscaped('A') = "\u0041"
- *
- *
- * @param ch the character to convert, may be null
- * @return the escaped Unicode string, null if null input
- */
- public static String unicodeEscaped(final Character ch) {
- if (ch == null) {
- return null;
- }
- return unicodeEscaped(ch.charValue());
- }
-
- //--------------------------------------------------------------------------
- /**
- * Checks whether the character is ASCII 7 bit.
- *
- *
- * CharUtils.isAscii('a') = true
- * CharUtils.isAscii('A') = true
- * CharUtils.isAscii('3') = true
- * CharUtils.isAscii('-') = true
- * CharUtils.isAscii('\n') = true
- * CharUtils.isAscii('©') = false
- *
- *
- * @param ch the character to check
- * @return true if less than 128
- */
- public static boolean isAscii(final char ch) {
- return ch < 128;
- }
-
- /**
- * Checks whether the character is ASCII 7 bit printable.
- *
- *
- * CharUtils.isAsciiPrintable('a') = true
- * CharUtils.isAsciiPrintable('A') = true
- * CharUtils.isAsciiPrintable('3') = true
- * CharUtils.isAsciiPrintable('-') = true
- * CharUtils.isAsciiPrintable('\n') = false
- * CharUtils.isAsciiPrintable('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 32 and 126 inclusive
- */
- public static boolean isAsciiPrintable(final char ch) {
- return ch >= 32 && ch < 127;
- }
-
- /**
- * Checks whether the character is ASCII 7 bit control.
- *
- *
- * CharUtils.isAsciiControl('a') = false
- * CharUtils.isAsciiControl('A') = false
- * CharUtils.isAsciiControl('3') = false
- * CharUtils.isAsciiControl('-') = false
- * CharUtils.isAsciiControl('\n') = true
- * CharUtils.isAsciiControl('©') = false
- *
- *
- * @param ch the character to check
- * @return true if less than 32 or equals 127
- */
- public static boolean isAsciiControl(final char ch) {
- return ch < 32 || ch == 127;
- }
-
- /**
- * Checks whether the character is ASCII 7 bit alphabetic.
- *
- *
- * CharUtils.isAsciiAlpha('a') = true
- * CharUtils.isAsciiAlpha('A') = true
- * CharUtils.isAsciiAlpha('3') = false
- * CharUtils.isAsciiAlpha('-') = false
- * CharUtils.isAsciiAlpha('\n') = false
- * CharUtils.isAsciiAlpha('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 65 and 90 or 97 and 122 inclusive
- */
- public static boolean isAsciiAlpha(final char ch) {
- return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch);
- }
-
- /**
- * Checks whether the character is ASCII 7 bit alphabetic upper case.
- *
- *
- * CharUtils.isAsciiAlphaUpper('a') = false
- * CharUtils.isAsciiAlphaUpper('A') = true
- * CharUtils.isAsciiAlphaUpper('3') = false
- * CharUtils.isAsciiAlphaUpper('-') = false
- * CharUtils.isAsciiAlphaUpper('\n') = false
- * CharUtils.isAsciiAlphaUpper('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 65 and 90 inclusive
- */
- public static boolean isAsciiAlphaUpper(final char ch) {
- return ch >= 'A' && ch <= 'Z';
- }
-
- /**
- * Checks whether the character is ASCII 7 bit alphabetic lower case.
- *
- *
- * CharUtils.isAsciiAlphaLower('a') = true
- * CharUtils.isAsciiAlphaLower('A') = false
- * CharUtils.isAsciiAlphaLower('3') = false
- * CharUtils.isAsciiAlphaLower('-') = false
- * CharUtils.isAsciiAlphaLower('\n') = false
- * CharUtils.isAsciiAlphaLower('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 97 and 122 inclusive
- */
- public static boolean isAsciiAlphaLower(final char ch) {
- return ch >= 'a' && ch <= 'z';
- }
-
- /**
- * Checks whether the character is ASCII 7 bit numeric.
- *
- *
- * CharUtils.isAsciiNumeric('a') = false
- * CharUtils.isAsciiNumeric('A') = false
- * CharUtils.isAsciiNumeric('3') = true
- * CharUtils.isAsciiNumeric('-') = false
- * CharUtils.isAsciiNumeric('\n') = false
- * CharUtils.isAsciiNumeric('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 48 and 57 inclusive
- */
- public static boolean isAsciiNumeric(final char ch) {
- return ch >= '0' && ch <= '9';
- }
-
- /**
- * Checks whether the character is ASCII 7 bit numeric.
- *
- *
- * CharUtils.isAsciiAlphanumeric('a') = true
- * CharUtils.isAsciiAlphanumeric('A') = true
- * CharUtils.isAsciiAlphanumeric('3') = true
- * CharUtils.isAsciiAlphanumeric('-') = false
- * CharUtils.isAsciiAlphanumeric('\n') = false
- * CharUtils.isAsciiAlphanumeric('©') = false
- *
- *
- * @param ch the character to check
- * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
- */
- public static boolean isAsciiAlphanumeric(final char ch) {
- return isAsciiAlpha(ch) || isAsciiNumeric(ch);
- }
-
- /**
- * Compares two {@code char} values numerically. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code char} to compare
- * @param y the second {@code char} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code x < y}; and
- * a value greater than {@code 0} if {@code x > y}
- * @since 3.4
- */
- public static int compare(final char x, final char y) {
- return x-y;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ClassUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ClassUtils.java
deleted file mode 100644
index 8d3878d5..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ClassUtils.java
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Operates on classes without using reflection.
- *
- * This class handles invalid {@code null} inputs as best it can.
- * Each method documents its behaviour in more detail.
- *
- * The notion of a {@code canonical name} includes the human
- * readable name for the type, for example {@code int[]}. The
- * non-canonical method variants work with the JVM names, such as
- * {@code [I}.
- *
- * @since 2.0
- */
-public class ClassUtils {
-
- /**
- * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}.
- * @since 3.2
- */
- public enum Interfaces {
- INCLUDE, EXCLUDE
- }
-
- /**
- * The package separator character: '.' == {@value}.
- */
- public static final char PACKAGE_SEPARATOR_CHAR = '.';
-
- /**
- * The package separator String: ".".
- */
- public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
-
- /**
- * The inner class separator character: '$' == {@value}.
- */
- public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
-
- /**
- * The inner class separator String: {@code "$"}.
- */
- public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
-
- /**
- * Maps names of primitives to their corresponding primitive {@code Class}es.
- */
- private static final Map> namePrimitiveMap = new HashMap<>();
- static {
- namePrimitiveMap.put("boolean", Boolean.TYPE);
- namePrimitiveMap.put("byte", Byte.TYPE);
- namePrimitiveMap.put("char", Character.TYPE);
- namePrimitiveMap.put("short", Short.TYPE);
- namePrimitiveMap.put("int", Integer.TYPE);
- namePrimitiveMap.put("long", Long.TYPE);
- namePrimitiveMap.put("double", Double.TYPE);
- namePrimitiveMap.put("float", Float.TYPE);
- namePrimitiveMap.put("void", Void.TYPE);
- }
-
- /**
- * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}.
- */
- private static final Map, Class>> primitiveWrapperMap = new HashMap<>();
- static {
- primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
- primitiveWrapperMap.put(Byte.TYPE, Byte.class);
- primitiveWrapperMap.put(Character.TYPE, Character.class);
- primitiveWrapperMap.put(Short.TYPE, Short.class);
- primitiveWrapperMap.put(Integer.TYPE, Integer.class);
- primitiveWrapperMap.put(Long.TYPE, Long.class);
- primitiveWrapperMap.put(Double.TYPE, Double.class);
- primitiveWrapperMap.put(Float.TYPE, Float.class);
- primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
- }
-
- /**
- * Maps wrapper {@code Class}es to their corresponding primitive types.
- */
- private static final Map, Class>> wrapperPrimitiveMap = new HashMap<>();
- static {
- for (final Map.Entry, Class>> entry : primitiveWrapperMap.entrySet()) {
- final Class> primitiveClass = entry.getKey();
- final Class> wrapperClass = entry.getValue();
- if (!primitiveClass.equals(wrapperClass)) {
- wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
- }
- }
- }
-
- /**
- * Maps a primitive class name to its corresponding abbreviation used in array class names.
- */
- private static final Map abbreviationMap;
-
- /**
- * Maps an abbreviation used in array class names to corresponding primitive class name.
- */
- private static final Map reverseAbbreviationMap;
-
- /**
- * Feed abbreviation maps
- */
- static {
- final Map m = new HashMap<>();
- m.put("int", "I");
- m.put("boolean", "Z");
- m.put("float", "F");
- m.put("long", "J");
- m.put("short", "S");
- m.put("byte", "B");
- m.put("double", "D");
- m.put("char", "C");
- final Map r = new HashMap<>();
- for (final Map.Entry e : m.entrySet()) {
- r.put(e.getValue(), e.getKey());
- }
- abbreviationMap = Collections.unmodifiableMap(m);
- reverseAbbreviationMap = Collections.unmodifiableMap(r);
- }
-
- /**
- * ClassUtils instances should NOT be constructed in standard programming.
- * Instead, the class should be used as
- * {@code ClassUtils.getShortClassName(cls)}.
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
- */
- public ClassUtils() {
- super();
- }
-
- // Short class name
- // ----------------------------------------------------------------------
- /**
- * Gets the class name minus the package name for an {@code Object}.
- *
- * @param object the class to get the short name for, may be null
- * @param valueIfNull the value to return if null
- * @return the class name of the object without the package name, or the null value
- */
- public static String getShortClassName(final Object object, final String valueIfNull) {
- if (object == null) {
- return valueIfNull;
- }
- return getShortClassName(object.getClass());
- }
-
- /**
- * Gets the class name minus the package name from a {@code Class}.
- *
- * Consider using the Java 5 API {@link Class#getSimpleName()} instead.
- * The one known difference is that this code will return {@code "Map.Entry"} while
- * the {@code java.lang.Class} variant will simply return {@code "Entry"}.
- *
- * @param cls the class to get the short name for.
- * @return the class name without the package name or an empty string
- */
- public static String getShortClassName(final Class> cls) {
- if (cls == null) {
- return StringUtils.EMPTY;
- }
- return getShortClassName(cls.getName());
- }
-
- /**
- * Gets the class name minus the package name from a String.
- *
- * The string passed in is assumed to be a class name - it is not checked.
-
- * Note that this method differs from Class.getSimpleName() in that this will
- * return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply
- * return {@code "Entry"}.
- *
- * @param className the className to get the short name for
- * @return the class name of the class without the package name or an empty string
- */
- public static String getShortClassName(String className) {
- if (StringUtils.isEmpty(className)) {
- return StringUtils.EMPTY;
- }
-
- final StringBuilder arrayPrefix = new StringBuilder();
-
- // Handle array encoding
- if (className.startsWith("[")) {
- while (className.charAt(0) == '[') {
- className = className.substring(1);
- arrayPrefix.append("[]");
- }
- // Strip Object type encoding
- if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
- className = className.substring(1, className.length() - 1);
- }
-
- if (reverseAbbreviationMap.containsKey(className)) {
- className = reverseAbbreviationMap.get(className);
- }
- }
-
- final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
- final int innerIdx = className.indexOf(
- INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
- String out = className.substring(lastDotIdx + 1);
- if (innerIdx != -1) {
- out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
- }
- return out + arrayPrefix;
- }
-
- /**
- * Null-safe version of aClass.getSimpleName()
- *
- * @param cls the class for which to get the simple name; may be null
- * @return the simple class name.
- * @since 3.0
- * @see Class#getSimpleName()
- */
- public static String getSimpleName(final Class> cls) {
- return getSimpleName(cls, StringUtils.EMPTY);
- }
-
- /**
- * Null-safe version of aClass.getSimpleName()
- *
- * @param cls the class for which to get the simple name; may be null
- * @param valueIfNull the value to return if null
- * @return the simple class name or {@code valueIfNull}
- * @since 3.0
- * @see Class#getSimpleName()
- */
- public static String getSimpleName(final Class> cls, String valueIfNull) {
- return cls == null ? valueIfNull : cls.getSimpleName();
- }
-
- /**
- * Null-safe version of aClass.getSimpleName()
- *
- * @param object the object for which to get the simple class name; may be null
- * @return the simple class name or the empty String
- * @since 3.7
- * @see Class#getSimpleName()
- */
- public static String getSimpleName(final Object object) {
- return getSimpleName(object, StringUtils.EMPTY);
- }
-
- /**
- * Null-safe version of aClass.getSimpleName()
- *
- * @param object the object for which to get the simple class name; may be null
- * @param valueIfNull the value to return if object is null
- * @return the simple class name or {@code valueIfNull}
- * @since 3.0
- * @see Class#getSimpleName()
- */
- public static String getSimpleName(final Object object, final String valueIfNull) {
- return object == null ? valueIfNull : object.getClass().getSimpleName();
- }
-
- /**
- * Null-safe version of Class.getName()
- *
- * @param cls the class for which to get the class name; may be null
- * @return the class name or the empty String.
- * @since 3.7
- * @see Class#getSimpleName()
- */
- public static String getName(final Class> cls) {
- return getName(cls, StringUtils.EMPTY);
- }
-
- /**
- * Null-safe version of aClass.getName()
- *
- * @param cls the class for which to get the class name; may be null
- * @param valueIfNull the return value if cls is null
- * @return the class name or {@code valueIfNull}
- * @since 3.7
- * @see Class#getName()
- */
- public static String getName(final Class> cls, final String valueIfNull) {
- return cls == null ? valueIfNull : cls.getName();
- }
-
- /**
- * Null-safe version of Class.getName()
- *
- * @param object the object for which to get the class name; may be null
- * @return the class name or the empty String
- * @since 3.7
- * @see Class#getSimpleName()
- */
- public static String getName(final Object object) {
- return getName(object, StringUtils.EMPTY);
- }
-
- /**
- * Null-safe version of aClass.getSimpleName()
- *
- * @param object the object for which to get the class name; may be null
- * @param valueIfNull the value to return if object is null
- * @return the class name or {@code valueIfNull}
- * @since 3.0
- * @see Class#getName()
- */
- public static String getName(final Object object, final String valueIfNull) {
- return object == null ? valueIfNull : object.getClass().getName();
- }
-
- // Package name
- // ----------------------------------------------------------------------
- /**
- * Gets the package name of an {@code Object}.
- *
- * @param object the class to get the package name for, may be null
- * @param valueIfNull the value to return if null
- * @return the package name of the object, or the null value
- */
- public static String getPackageName(final Object object, final String valueIfNull) {
- if (object == null) {
- return valueIfNull;
- }
- return getPackageName(object.getClass());
- }
-
- /**
- * Gets the package name of a {@code Class}.
- *
- * @param cls the class to get the package name for, may be {@code null}.
- * @return the package name or an empty string
- */
- public static String getPackageName(final Class> cls) {
- if (cls == null) {
- return StringUtils.EMPTY;
- }
- return getPackageName(cls.getName());
- }
-
- /**
- * Gets the package name from a {@code String}.
- *
- * The string passed in is assumed to be a class name - it is not checked.
- * If the class is unpackaged, return an empty string.
- *
- * @param className the className to get the package name for, may be {@code null}
- * @return the package name or an empty string
- */
- public static String getPackageName(String className) {
- if (StringUtils.isEmpty(className)) {
- return StringUtils.EMPTY;
- }
-
- // Strip array encoding
- while (className.charAt(0) == '[') {
- className = className.substring(1);
- }
- // Strip Object type encoding
- if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
- className = className.substring(1);
- }
-
- final int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
- if (i == -1) {
- return StringUtils.EMPTY;
- }
- return className.substring(0, i);
- }
-
- // Abbreviated name
- // ----------------------------------------------------------------------
- /**
- * Gets the abbreviated name of a {@code Class}.
- *
- * @param cls the class to get the abbreviated name for, may be {@code null}
- * @param len the desired length of the abbreviated name
- * @return the abbreviated name or an empty string
- * @throws IllegalArgumentException if len <= 0
- * @see #getAbbreviatedName(String, int)
- * @since 3.4
- */
- public static String getAbbreviatedName(final Class> cls, final int len) {
- if (cls == null) {
- return StringUtils.EMPTY;
- }
- return getAbbreviatedName(cls.getName(), len);
- }
-
- /**
- * Gets the abbreviated class name from a {@code String}.
- *
- * The string passed in is assumed to be a class name - it is not checked.
- *
- * The abbreviation algorithm will shorten the class name, usually without
- * significant loss of meaning.
- * The abbreviated class name will always include the complete package hierarchy.
- * If enough space is available, rightmost sub-packages will be displayed in full
- * length.
- *
- *
- * Examples
- * className len return
- * null 1 ""
- * "java.lang.String" 5 "j.l.String"
- * "java.lang.String" 15 "j.lang.String"
- * "java.lang.String" 30 "java.lang.String"
- *
- * @param className the className to get the abbreviated name for, may be {@code null}
- * @param len the desired length of the abbreviated name
- * @return the abbreviated name or an empty string
- * @throws IllegalArgumentException if len <= 0
- * @since 3.4
- */
- public static String getAbbreviatedName(final String className, final int len) {
- if (len <= 0) {
- throw new IllegalArgumentException("len must be > 0");
- }
- if (className == null) {
- return StringUtils.EMPTY;
- }
-
- int availableSpace = len;
- final int packageLevels = StringUtils.countMatches(className, '.');
- final String[] output = new String[packageLevels + 1];
- int endIndex = className.length() - 1;
- for (int level = packageLevels; level >= 0; level--) {
- final int startIndex = className.lastIndexOf('.', endIndex);
- final String part = className.substring(startIndex + 1, endIndex + 1);
- availableSpace -= part.length();
- if (level > 0) {
- // all elements except top level require an additional char space
- availableSpace--;
- }
- if (level == packageLevels) {
- // ClassName is always complete
- output[level] = part;
- } else {
- if (availableSpace > 0) {
- output[level] = part;
- } else {
- // if no space is left still the first char is used
- output[level] = part.substring(0, 1);
- }
- }
- endIndex = startIndex - 1;
- }
-
- return StringUtils.join(output, '.');
- }
-
- // Superclasses/Superinterfaces
- // ----------------------------------------------------------------------
- /**
- * Gets a {@code List} of superclasses for the given class.
- *
- * @param cls the class to look up, may be {@code null}
- * @return the {@code List} of superclasses in order going up from this one
- * {@code null} if null input
- */
- public static List> getAllSuperclasses(final Class> cls) {
- if (cls == null) {
- return null;
- }
- final List> classes = new ArrayList<>();
- Class> superclass = cls.getSuperclass();
- while (superclass != null) {
- classes.add(superclass);
- superclass = superclass.getSuperclass();
- }
- return classes;
- }
-
- /**
- * Gets a {@code List} of all interfaces implemented by the given
- * class and its superclasses.
- *
- * The order is determined by looking through each interface in turn as
- * declared in the source file and following its hierarchy up. Then each
- * superclass is considered in the same way. Later duplicates are ignored,
- * so the order is maintained.
- *
- * @param cls the class to look up, may be {@code null}
- * @return the {@code List} of interfaces in order,
- * {@code null} if null input
- */
- public static List> getAllInterfaces(final Class> cls) {
- if (cls == null) {
- return null;
- }
-
- final LinkedHashSet> interfacesFound = new LinkedHashSet<>();
- getAllInterfaces(cls, interfacesFound);
-
- return new ArrayList<>(interfacesFound);
- }
-
- /**
- * Get the interfaces for the specified class.
- *
- * @param cls the class to look up, may be {@code null}
- * @param interfacesFound the {@code Set} of interfaces for the class
- */
- private static void getAllInterfaces(Class> cls, final HashSet> interfacesFound) {
- while (cls != null) {
- final Class>[] interfaces = cls.getInterfaces();
-
- for (final Class> i : interfaces) {
- if (interfacesFound.add(i)) {
- getAllInterfaces(i, interfacesFound);
- }
- }
-
- cls = cls.getSuperclass();
- }
- }
-
- // Convert list
- // ----------------------------------------------------------------------
- /**
- * Given a {@code List} of class names, this method converts them into classes.
- *
- * A new {@code List} is returned. If the class name cannot be found, {@code null}
- * is stored in the {@code List}. If the class name in the {@code List} is
- * {@code null}, {@code null} is stored in the output {@code List}.
- *
- * @param classNames the classNames to change
- * @return a {@code List} of Class objects corresponding to the class names,
- * {@code null} if null input
- * @throws ClassCastException if classNames contains a non String entry
- */
- public static List> convertClassNamesToClasses(final List classNames) {
- if (classNames == null) {
- return null;
- }
- final List> classes = new ArrayList<>(classNames.size());
- for (final String className : classNames) {
- try {
- classes.add(Class.forName(className));
- } catch (final Exception ex) {
- classes.add(null);
- }
- }
- return classes;
- }
-
- /**
- * Given a {@code List} of {@code Class} objects, this method converts
- * them into class names.
- *
- * A new {@code List} is returned. {@code null} objects will be copied into
- * the returned list as {@code null}.
- *
- * @param classes the classes to change
- * @return a {@code List} of class names corresponding to the Class objects,
- * {@code null} if null input
- * @throws ClassCastException if {@code classes} contains a non-{@code Class} entry
- */
- public static List convertClassesToClassNames(final List> classes) {
- if (classes == null) {
- return null;
- }
- final List classNames = new ArrayList<>(classes.size());
- for (final Class> cls : classes) {
- if (cls == null) {
- classNames.add(null);
- } else {
- classNames.add(cls.getName());
- }
- }
- return classNames;
- }
-
- // Is assignable
- // ----------------------------------------------------------------------
- /**
- * Checks if an array of Classes can be assigned to another array of Classes.
- *
- * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
- * Class pair in the input arrays. It can be used to check if a set of arguments
- * (the first parameter) are suitably compatible with a set of method parameter types
- * (the second parameter).
- *
- * Unlike the {@link Class#isAssignableFrom(Class)} method, this
- * method takes into account widenings of primitive classes and
- * {@code null}s.
- *
- * Primitive widenings allow an int to be assigned to a {@code long},
- * {@code float} or {@code double}. This method returns the correct
- * result for these cases.
- *
- * {@code Null} may be assigned to any reference type. This method will
- * return {@code true} if {@code null} is passed in and the toClass is
- * non-primitive.
- *
- * Specifically, this method tests whether the type represented by the
- * specified {@code Class} parameter can be converted to the type
- * represented by this {@code Class} object via an identity conversion
- * widening primitive or widening reference conversion. See
- * The Java Language Specification ,
- * sections 5.1.1, 5.1.2 and 5.1.4 for details.
- *
- * Since Lang 3.0, this method will default behavior for
- * calculating assignability between primitive and wrapper types corresponding
- * to the running Java version ; i.e. autoboxing will be the default
- * behavior in VMs running Java versions > 1.5.
- *
- * @param classArray the array of Classes to check, may be {@code null}
- * @param toClassArray the array of Classes to try to assign into, may be {@code null}
- * @return {@code true} if assignment possible
- */
- public static boolean isAssignable(final Class>[] classArray, final Class>... toClassArray) {
- return isAssignable(classArray, toClassArray, true);
- }
-
- /**
- * Checks if an array of Classes can be assigned to another array of Classes.
- *
- * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
- * Class pair in the input arrays. It can be used to check if a set of arguments
- * (the first parameter) are suitably compatible with a set of method parameter types
- * (the second parameter).
- *
- * Unlike the {@link Class#isAssignableFrom(Class)} method, this
- * method takes into account widenings of primitive classes and
- * {@code null}s.
- *
- * Primitive widenings allow an int to be assigned to a {@code long},
- * {@code float} or {@code double}. This method returns the correct
- * result for these cases.
- *
- * {@code Null} may be assigned to any reference type. This method will
- * return {@code true} if {@code null} is passed in and the toClass is
- * non-primitive.
- *
- * Specifically, this method tests whether the type represented by the
- * specified {@code Class} parameter can be converted to the type
- * represented by this {@code Class} object via an identity conversion
- * widening primitive or widening reference conversion. See
- * The Java Language Specification ,
- * sections 5.1.1, 5.1.2 and 5.1.4 for details.
- *
- * @param classArray the array of Classes to check, may be {@code null}
- * @param toClassArray the array of Classes to try to assign into, may be {@code null}
- * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
- * @return {@code true} if assignment possible
- */
- public static boolean isAssignable(Class>[] classArray, Class>[] toClassArray, final boolean autoboxing) {
- if (!ArrayUtils.isSameLength(classArray, toClassArray)) {
- return false;
- }
- if (classArray == null) {
- classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
- }
- if (toClassArray == null) {
- toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
- }
- for (int i = 0; i < classArray.length; i++) {
- if (!isAssignable(classArray[i], toClassArray[i], autoboxing)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns whether the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
- * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
- *
- * @param type
- * The class to query or null.
- * @return true if the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
- * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
- * @since 3.1
- */
- public static boolean isPrimitiveOrWrapper(final Class> type) {
- if (type == null) {
- return false;
- }
- return type.isPrimitive() || isPrimitiveWrapper(type);
- }
-
- /**
- * Returns whether the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
- * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
- *
- * @param type
- * The class to query or null.
- * @return true if the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
- * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
- * @since 3.1
- */
- public static boolean isPrimitiveWrapper(final Class> type) {
- return wrapperPrimitiveMap.containsKey(type);
- }
-
- /**
- * Checks if one {@code Class} can be assigned to a variable of
- * another {@code Class}.
- *
- * Unlike the {@link Class#isAssignableFrom(Class)} method,
- * this method takes into account widenings of primitive classes and
- * {@code null}s.
- *
- * Primitive widenings allow an int to be assigned to a long, float or
- * double. This method returns the correct result for these cases.
- *
- * {@code Null} may be assigned to any reference type. This method
- * will return {@code true} if {@code null} is passed in and the
- * toClass is non-primitive.
- *
- * Specifically, this method tests whether the type represented by the
- * specified {@code Class} parameter can be converted to the type
- * represented by this {@code Class} object via an identity conversion
- * widening primitive or widening reference conversion. See
- * The Java Language Specification ,
- * sections 5.1.1, 5.1.2 and 5.1.4 for details.
- *
- * Since Lang 3.0, this method will default behavior for
- * calculating assignability between primitive and wrapper types corresponding
- * to the running Java version ; i.e. autoboxing will be the default
- * behavior in VMs running Java versions > 1.5.
- *
- * @param cls the Class to check, may be null
- * @param toClass the Class to try to assign into, returns false if null
- * @return {@code true} if assignment possible
- */
- public static boolean isAssignable(final Class> cls, final Class> toClass) {
- return isAssignable(cls, toClass, true);
- }
-
- /**
- * Checks if one {@code Class} can be assigned to a variable of
- * another {@code Class}.
- *
- * Unlike the {@link Class#isAssignableFrom(Class)} method,
- * this method takes into account widenings of primitive classes and
- * {@code null}s.
- *
- * Primitive widenings allow an int to be assigned to a long, float or
- * double. This method returns the correct result for these cases.
- *
- * {@code Null} may be assigned to any reference type. This method
- * will return {@code true} if {@code null} is passed in and the
- * toClass is non-primitive.
- *
- * Specifically, this method tests whether the type represented by the
- * specified {@code Class} parameter can be converted to the type
- * represented by this {@code Class} object via an identity conversion
- * widening primitive or widening reference conversion. See
- * The Java Language Specification ,
- * sections 5.1.1, 5.1.2 and 5.1.4 for details.
- *
- * @param cls the Class to check, may be null
- * @param toClass the Class to try to assign into, returns false if null
- * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
- * @return {@code true} if assignment possible
- */
- public static boolean isAssignable(Class> cls, final Class> toClass, final boolean autoboxing) {
- if (toClass == null) {
- return false;
- }
- // have to check for null, as isAssignableFrom doesn't
- if (cls == null) {
- return !toClass.isPrimitive();
- }
- //autoboxing:
- if (autoboxing) {
- if (cls.isPrimitive() && !toClass.isPrimitive()) {
- cls = primitiveToWrapper(cls);
- if (cls == null) {
- return false;
- }
- }
- if (toClass.isPrimitive() && !cls.isPrimitive()) {
- cls = wrapperToPrimitive(cls);
- if (cls == null) {
- return false;
- }
- }
- }
- if (cls.equals(toClass)) {
- return true;
- }
- if (cls.isPrimitive()) {
- if (!toClass.isPrimitive()) {
- return false;
- }
- if (Integer.TYPE.equals(cls)) {
- return Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
- || Double.TYPE.equals(toClass);
- }
- if (Long.TYPE.equals(cls)) {
- return Float.TYPE.equals(toClass)
- || Double.TYPE.equals(toClass);
- }
- if (Boolean.TYPE.equals(cls)) {
- return false;
- }
- if (Double.TYPE.equals(cls)) {
- return false;
- }
- if (Float.TYPE.equals(cls)) {
- return Double.TYPE.equals(toClass);
- }
- if (Character.TYPE.equals(cls)) {
- return Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
- || Double.TYPE.equals(toClass);
- }
- if (Short.TYPE.equals(cls)) {
- return Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
- || Double.TYPE.equals(toClass);
- }
- if (Byte.TYPE.equals(cls)) {
- return Short.TYPE.equals(toClass)
- || Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
- || Double.TYPE.equals(toClass);
- }
- // should never get here
- return false;
- }
- return toClass.isAssignableFrom(cls);
- }
-
- /**
- * Converts the specified primitive Class object to its corresponding
- * wrapper Class object.
- *
- * NOTE: From v2.2, this method handles {@code Void.TYPE},
- * returning {@code Void.TYPE}.
- *
- * @param cls the class to convert, may be null
- * @return the wrapper class for {@code cls} or {@code cls} if
- * {@code cls} is not a primitive. {@code null} if null input.
- * @since 2.1
- */
- public static Class> primitiveToWrapper(final Class> cls) {
- Class> convertedClass = cls;
- if (cls != null && cls.isPrimitive()) {
- convertedClass = primitiveWrapperMap.get(cls);
- }
- return convertedClass;
- }
-
- /**
- * Converts the specified array of primitive Class objects to an array of
- * its corresponding wrapper Class objects.
- *
- * @param classes the class array to convert, may be null or empty
- * @return an array which contains for each given class, the wrapper class or
- * the original class if class is not a primitive. {@code null} if null input.
- * Empty array if an empty array passed in.
- * @since 2.1
- */
- public static Class>[] primitivesToWrappers(final Class>... classes) {
- if (classes == null) {
- return null;
- }
-
- if (classes.length == 0) {
- return classes;
- }
-
- final Class>[] convertedClasses = new Class[classes.length];
- for (int i = 0; i < classes.length; i++) {
- convertedClasses[i] = primitiveToWrapper(classes[i]);
- }
- return convertedClasses;
- }
-
- /**
- * Converts the specified wrapper class to its corresponding primitive
- * class.
- *
- * This method is the counter part of {@code primitiveToWrapper()}.
- * If the passed in class is a wrapper class for a primitive type, this
- * primitive type will be returned (e.g. {@code Integer.TYPE} for
- * {@code Integer.class}). For other classes, or if the parameter is
- * null , the return value is null .
- *
- * @param cls the class to convert, may be null
- * @return the corresponding primitive type if {@code cls} is a
- * wrapper class, null otherwise
- * @see #primitiveToWrapper(Class)
- * @since 2.4
- */
- public static Class> wrapperToPrimitive(final Class> cls) {
- return wrapperPrimitiveMap.get(cls);
- }
-
- /**
- * Converts the specified array of wrapper Class objects to an array of
- * its corresponding primitive Class objects.
- *
- * This method invokes {@code wrapperToPrimitive()} for each element
- * of the passed in array.
- *
- * @param classes the class array to convert, may be null or empty
- * @return an array which contains for each given class, the primitive class or
- * null if the original class is not a wrapper class. {@code null} if null input.
- * Empty array if an empty array passed in.
- * @see #wrapperToPrimitive(Class)
- * @since 2.4
- */
- public static Class>[] wrappersToPrimitives(final Class>... classes) {
- if (classes == null) {
- return null;
- }
-
- if (classes.length == 0) {
- return classes;
- }
-
- final Class>[] convertedClasses = new Class[classes.length];
- for (int i = 0; i < classes.length; i++) {
- convertedClasses[i] = wrapperToPrimitive(classes[i]);
- }
- return convertedClasses;
- }
-
- // Inner class
- // ----------------------------------------------------------------------
- /**
- * Is the specified class an inner class or static nested class.
- *
- * @param cls the class to check, may be null
- * @return {@code true} if the class is an inner or static nested class,
- * false if not or {@code null}
- */
- public static boolean isInnerClass(final Class> cls) {
- return cls != null && cls.getEnclosingClass() != null;
- }
-
- // Class loading
- // ----------------------------------------------------------------------
- /**
- * Returns the class represented by {@code className} using the
- * {@code classLoader}. This implementation supports the syntaxes
- * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
- * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
- *
- * @param classLoader the class loader to use to load the class
- * @param className the class name
- * @param initialize whether the class must be initialized
- * @return the class represented by {@code className} using the {@code classLoader}
- * @throws ClassNotFoundException if the class is not found
- */
- public static Class> getClass(
- final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException {
- try {
- Class> clazz;
- if (namePrimitiveMap.containsKey(className)) {
- clazz = namePrimitiveMap.get(className);
- } else {
- clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
- }
- return clazz;
- } catch (final ClassNotFoundException ex) {
- // allow path separators (.) as inner class name separators
- final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
-
- if (lastDotIndex != -1) {
- try {
- return getClass(classLoader, className.substring(0, lastDotIndex) +
- INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
- initialize);
- } catch (final ClassNotFoundException ex2) { // NOPMD
- // ignore exception
- }
- }
-
- throw ex;
- }
- }
-
- /**
- * Returns the (initialized) class represented by {@code className}
- * using the {@code classLoader}. This implementation supports
- * the syntaxes "{@code java.util.Map.Entry[]}",
- * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
- * and "{@code [Ljava.util.Map$Entry;}".
- *
- * @param classLoader the class loader to use to load the class
- * @param className the class name
- * @return the class represented by {@code className} using the {@code classLoader}
- * @throws ClassNotFoundException if the class is not found
- */
- public static Class> getClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException {
- return getClass(classLoader, className, true);
- }
-
- /**
- * Returns the (initialized) class represented by {@code className}
- * using the current thread's context class loader. This implementation
- * supports the syntaxes "{@code java.util.Map.Entry[]}",
- * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
- * and "{@code [Ljava.util.Map$Entry;}".
- *
- * @param className the class name
- * @return the class represented by {@code className} using the current thread's context class loader
- * @throws ClassNotFoundException if the class is not found
- */
- public static Class> getClass(final String className) throws ClassNotFoundException {
- return getClass(className, true);
- }
-
- /**
- * Returns the class represented by {@code className} using the
- * current thread's context class loader. This implementation supports the
- * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
- * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
- *
- * @param className the class name
- * @param initialize whether the class must be initialized
- * @return the class represented by {@code className} using the current thread's context class loader
- * @throws ClassNotFoundException if the class is not found
- */
- public static Class> getClass(final String className, final boolean initialize) throws ClassNotFoundException {
- final ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
- final ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL;
- return getClass(loader, className, initialize);
- }
-
- // Public method
- // ----------------------------------------------------------------------
- /**
- * Returns the desired Method much like {@code Class.getMethod}, however
- * it ensures that the returned Method is from a public class or interface and not
- * from an anonymous inner class. This means that the Method is invokable and
- * doesn't fall foul of Java bug
- * 4071957 ).
- *
- *
- * Set set = Collections.unmodifiableSet(...);
- * Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty", new Class[0]);
- * Object result = method.invoke(set, new Object[]);
- *
- *
- * @param cls the class to check, not null
- * @param methodName the name of the method
- * @param parameterTypes the list of parameters
- * @return the method
- * @throws NullPointerException if the class is null
- * @throws SecurityException if a security violation occurred
- * @throws NoSuchMethodException if the method is not found in the given class
- * or if the method doesn't conform with the requirements
- */
- public static Method getPublicMethod(final Class> cls, final String methodName, final Class>... parameterTypes)
- throws NoSuchMethodException {
-
- final Method declaredMethod = cls.getMethod(methodName, parameterTypes);
- if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
- return declaredMethod;
- }
-
- final List> candidateClasses = new ArrayList<>();
- candidateClasses.addAll(getAllInterfaces(cls));
- candidateClasses.addAll(getAllSuperclasses(cls));
-
- for (final Class> candidateClass : candidateClasses) {
- if (!Modifier.isPublic(candidateClass.getModifiers())) {
- continue;
- }
- Method candidateMethod;
- try {
- candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
- } catch (final NoSuchMethodException ex) {
- continue;
- }
- if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
- return candidateMethod;
- }
- }
-
- throw new NoSuchMethodException("Can't find a public method for " +
- methodName + " " + ArrayUtils.toString(parameterTypes));
- }
-
- // ----------------------------------------------------------------------
- /**
- * Converts a class name to a JLS style class name.
- *
- * @param className the class name
- * @return the converted name
- */
- private static String toCanonicalName(String className) {
- className = StringUtils.deleteWhitespace(className);
- Validate.notNull(className, "className must not be null.");
- if (className.endsWith("[]")) {
- final StringBuilder classNameBuffer = new StringBuilder();
- while (className.endsWith("[]")) {
- className = className.substring(0, className.length() - 2);
- classNameBuffer.append("[");
- }
- final String abbreviation = abbreviationMap.get(className);
- if (abbreviation != null) {
- classNameBuffer.append(abbreviation);
- } else {
- classNameBuffer.append("L").append(className).append(";");
- }
- className = classNameBuffer.toString();
- }
- return className;
- }
-
- /**
- * Converts an array of {@code Object} in to an array of {@code Class} objects.
- * If any of these objects is null, a null element will be inserted into the array.
- *
- * This method returns {@code null} for a {@code null} input array.
- *
- * @param array an {@code Object} array
- * @return a {@code Class} array, {@code null} if null array input
- * @since 2.4
- */
- public static Class>[] toClass(final Object... array) {
- if (array == null) {
- return null;
- } else if (array.length == 0) {
- return ArrayUtils.EMPTY_CLASS_ARRAY;
- }
- final Class>[] classes = new Class[array.length];
- for (int i = 0; i < array.length; i++) {
- classes[i] = array[i] == null ? null : array[i].getClass();
- }
- return classes;
- }
-
- // Short canonical name
- // ----------------------------------------------------------------------
- /**
- * Gets the canonical name minus the package name for an {@code Object}.
- *
- * @param object the class to get the short name for, may be null
- * @param valueIfNull the value to return if null
- * @return the canonical name of the object without the package name, or the null value
- * @since 2.4
- */
- public static String getShortCanonicalName(final Object object, final String valueIfNull) {
- if (object == null) {
- return valueIfNull;
- }
- return getShortCanonicalName(object.getClass().getName());
- }
-
- /**
- * Gets the canonical class name for a {@code Class}.
- *
- * @param cls the class for which to get the canonical class name; may be null
- * @return the canonical name of the class, or the empty String
- * @since 3.7
- * @see Class#getCanonicalName()
- */
- public static String getCanonicalName(final Class> cls) {
- return getCanonicalName(cls, StringUtils.EMPTY);
- }
-
- /**
- * Gets the canonical name for a {@code Class}.
- *
- * @param cls the class for which to get the canonical class name; may be null
- * @param valueIfNull the return value if null
- * @return the canonical name of the class, or {@code valueIfNull}
- * @since 3.7
- * @see Class#getCanonicalName()
- */
- public static String getCanonicalName(final Class> cls, final String valueIfNull) {
- if (cls == null) {
- return valueIfNull;
- }
- final String canonicalName = cls.getCanonicalName();
- return canonicalName == null ? valueIfNull : canonicalName;
- }
-
- /**
- * Gets the canonical name for an {@code Object}.
- *
- * @param object the object for which to get the canonical class name; may be null
- * @return the canonical name of the object, or the empty String
- * @since 3.7
- * @see Class#getCanonicalName()
- */
- public static String getCanonicalName(final Object object) {
- return getCanonicalName(object, StringUtils.EMPTY);
- }
-
- /**
- * Gets the canonical name for an {@code Object}.
- *
- * @param object the object for which to get the canonical class name; may be null
- * @param valueIfNull the return value if null
- * @return the canonical name of the object or {@code valueIfNull}
- * @since 3.7
- * @see Class#getCanonicalName()
- */
- public static String getCanonicalName(final Object object, final String valueIfNull) {
- if (object == null) {
- return valueIfNull;
- }
- final String canonicalName = object.getClass().getCanonicalName();
- return canonicalName == null ? valueIfNull : canonicalName;
- }
-
- /**
- * Gets the canonical name minus the package name from a {@code Class}.
- *
- * @param cls the class for which to get the short canonical class name; may be null
- * @return the canonical name without the package name or an empty string
- * @since 2.4
- */
- public static String getShortCanonicalName(final Class> cls) {
- if (cls == null) {
- return StringUtils.EMPTY;
- }
- return getShortCanonicalName(cls.getName());
- }
-
- /**
- * Gets the canonical name minus the package name from a String.
- *
- * The string passed in is assumed to be a canonical name - it is not checked.
- *
- * @param canonicalName the class name to get the short name for
- * @return the canonical name of the class without the package name or an empty string
- * @since 2.4
- */
- public static String getShortCanonicalName(final String canonicalName) {
- return getShortClassName(getCanonicalName(canonicalName));
- }
-
- // Package name
- // ----------------------------------------------------------------------
- /**
- * Gets the package name from the canonical name of an {@code Object}.
- *
- * @param object the class to get the package name for, may be null
- * @param valueIfNull the value to return if null
- * @return the package name of the object, or the null value
- * @since 2.4
- */
- public static String getPackageCanonicalName(final Object object, final String valueIfNull) {
- if (object == null) {
- return valueIfNull;
- }
- return getPackageCanonicalName(object.getClass().getName());
- }
-
- /**
- * Gets the package name from the canonical name of a {@code Class}.
- *
- * @param cls the class to get the package name for, may be {@code null}.
- * @return the package name or an empty string
- * @since 2.4
- */
- public static String getPackageCanonicalName(final Class> cls) {
- if (cls == null) {
- return StringUtils.EMPTY;
- }
- return getPackageCanonicalName(cls.getName());
- }
-
- /**
- * Gets the package name from the canonical name.
- *
- * The string passed in is assumed to be a canonical name - it is not checked.
- * If the class is unpackaged, return an empty string.
- *
- * @param canonicalName the canonical name to get the package name for, may be {@code null}
- * @return the package name or an empty string
- * @since 2.4
- */
- public static String getPackageCanonicalName(final String canonicalName) {
- return getPackageName(getCanonicalName(canonicalName));
- }
-
- /**
- * Converts a given name of class into canonical format.
- * If name of class is not a name of array class it returns
- * unchanged name.
- * Example:
- *
- * {@code getCanonicalName("[I") = "int[]"}
- * {@code getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"}
- * {@code getCanonicalName("java.lang.String") = "java.lang.String"}
- *
- *
- *
- * @param className the name of class
- * @return canonical form of class name
- * @since 2.4
- */
- private static String getCanonicalName(String className) {
- className = StringUtils.deleteWhitespace(className);
- if (className == null) {
- return null;
- }
- int dim = 0;
- while (className.startsWith("[")) {
- dim++;
- className = className.substring(1);
- }
- if (dim < 1) {
- return className;
- }
- if (className.startsWith("L")) {
- className = className.substring(
- 1,
- className.endsWith(";")
- ? className.length() - 1
- : className.length());
- } else {
- if (!className.isEmpty()) {
- className = reverseAbbreviationMap.get(className.substring(0, 1));
- }
- }
- final StringBuilder canonicalClassNameBuffer = new StringBuilder(className);
- for (int i = 0; i < dim; i++) {
- canonicalClassNameBuffer.append("[]");
- }
- return canonicalClassNameBuffer.toString();
- }
-
- /**
- * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order,
- * excluding interfaces.
- *
- * @param type the type to get the class hierarchy from
- * @return Iterable an Iterable over the class hierarchy of the given class
- * @since 3.2
- */
- public static Iterable> hierarchy(final Class> type) {
- return hierarchy(type, Interfaces.EXCLUDE);
- }
-
- /**
- * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order.
- *
- * @param type the type to get the class hierarchy from
- * @param interfacesBehavior switch indicating whether to include or exclude interfaces
- * @return Iterable an Iterable over the class hierarchy of the given class
- * @since 3.2
- */
- public static Iterable> hierarchy(final Class> type, final Interfaces interfacesBehavior) {
- final Iterable> classes = new Iterable>() {
-
- @Override
- public Iterator> iterator() {
- final MutableObject> next = new MutableObject>(type);
- return new Iterator>() {
-
- @Override
- public boolean hasNext() {
- return next.getValue() != null;
- }
-
- @Override
- public Class> next() {
- final Class> result = next.getValue();
- next.setValue(result.getSuperclass());
- return result;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- };
- }
-
- };
- if (interfacesBehavior != Interfaces.INCLUDE) {
- return classes;
- }
- return new Iterable>() {
-
- @Override
- public Iterator> iterator() {
- final Set> seenInterfaces = new HashSet<>();
- final Iterator> wrapped = classes.iterator();
-
- return new Iterator>() {
- Iterator> interfaces = Collections.> emptySet().iterator();
-
- @Override
- public boolean hasNext() {
- return interfaces.hasNext() || wrapped.hasNext();
- }
-
- @Override
- public Class> next() {
- if (interfaces.hasNext()) {
- final Class> nextInterface = interfaces.next();
- seenInterfaces.add(nextInterface);
- return nextInterface;
- }
- final Class> nextSuperclass = wrapped.next();
- final Set> currentInterfaces = new LinkedHashSet<>();
- walkInterfaces(currentInterfaces, nextSuperclass);
- interfaces = currentInterfaces.iterator();
- return nextSuperclass;
- }
-
- private void walkInterfaces(final Set> addTo, final Class> c) {
- for (final Class> iface : c.getInterfaces()) {
- if (!seenInterfaces.contains(iface)) {
- addTo.add(iface);
- }
- walkInterfaces(addTo, iface);
- }
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- };
- }
- };
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeBuilder.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeBuilder.java
deleted file mode 100644
index 748c87bf..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeBuilder.java
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- *
- * Assists in implementing {@link Object#hashCode()} methods.
- *
- *
- *
- * This class enables a good hashCode method to be built for any class. It follows the rules laid out in
- * the book Effective Java by Joshua Bloch. Writing a
- * good hashCode method is actually quite difficult. This class aims to simplify the process.
- *
- *
- *
- * The following is the approach taken. When appending a data field, the current total is multiplied by the
- * multiplier then a relevant value
- * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
- * appending the integer 45 will create a hash code of 674, namely 17 * 37 + 45.
- *
- *
- *
- * All relevant fields from the object should be included in the hashCode method. Derived fields may be
- * excluded. In general, any field used in the equals method must be used in the hashCode
- * method.
- *
- *
- *
- * To use this class write code as follows:
- *
- *
- *
- * public class Person {
- * String name;
- * int age;
- * boolean smoker;
- * ...
- *
- * public int hashCode() {
- * // you pick a hard-coded, randomly chosen, non-zero, odd number
- * // ideally different for each class
- * return new HashCodeBuilder(17, 37).
- * append(name).
- * append(age).
- * append(smoker).
- * toHashCode();
- * }
- * }
- *
- *
- *
- * If required, the superclass hashCode() can be added using {@link #appendSuper}.
- *
- *
- *
- * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
- * usually private, the method, reflectionHashCode, uses AccessibleObject.setAccessible
- * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
- * are set up correctly. It is also slower than testing explicitly.
- *
- *
- *
- * A typical invocation for this method would look like:
- *
- *
- *
- * public int hashCode() {
- * return HashCodeBuilder.reflectionHashCode(this);
- * }
- *
- *
- * used by the reflectionHashCode methods.
- *
- * @since 1.0
- */
-public class HashCodeBuilder implements Builder {
- /**
- * The default initial value to use in reflection hash code building.
- */
- private static final int DEFAULT_INITIAL_VALUE = 17;
-
- /**
- * The default multiplier value to use in reflection hash code building.
- */
- private static final int DEFAULT_MULTIPLIER_VALUE = 37;
-
- /**
- *
- * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
- *
- *
- * @since 2.3
- */
- private static final ThreadLocal> REGISTRY = new ThreadLocal<>();
-
- /*
- * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
- * we are in the process of calculating.
- *
- * So we generate a one-to-one mapping from the original object to a new object.
- *
- * Now HashSet uses equals() to determine if two elements with the same hash code really
- * are equal, so we also need to ensure that the replacement objects are only equal
- * if the original objects are identical.
- *
- * The original implementation (2.4 and before) used the System.identityHashCode()
- * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
- *
- * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
- * to disambiguate the duplicate ids.
- */
-
- /**
- *
- * Returns the registry of objects being traversed by the reflection methods in the current thread.
- *
- *
- * @return Set the registry of objects being traversed
- * @since 2.3
- */
- static Set getRegistry() {
- return REGISTRY.get();
- }
-
- /**
- *
- * Returns true if the registry contains the given object. Used by the reflection methods to avoid
- * infinite loops.
- *
- *
- * @param value
- * The object to lookup in the registry.
- * @return boolean true if the registry contains the given object.
- * @since 2.3
- */
- static boolean isRegistered(final Object value) {
- final Set registry = getRegistry();
- return registry != null && registry.contains(new IDKey(value));
- }
-
- /**
- *
- * Appends the fields and values defined by the given object of the given Class.
- *
- *
- * @param object
- * the object to append details of
- * @param clazz
- * the class to append details of
- * @param builder
- * the builder to append to
- * @param useTransients
- * whether to use transient fields
- * @param excludeFields
- * Collection of String field names to exclude from use in calculation of hash code
- */
- private static void reflectionAppend(final Object object, final Class> clazz, final HashCodeBuilder builder, final boolean useTransients,
- final String[] excludeFields) {
- if (isRegistered(object)) {
- return;
- }
- try {
- register(object);
- final Field[] fields = clazz.getDeclaredFields();
- AccessibleObject.setAccessible(fields, true);
- for (final Field field : fields) {
- if (!ArrayUtils.contains(excludeFields, field.getName())
- && !field.getName().contains("$")
- && (useTransients || !Modifier.isTransient(field.getModifiers()))
- && !Modifier.isStatic(field.getModifiers())
- && !field.isAnnotationPresent(HashCodeExclude.class)) {
- try {
- final Object fieldValue = field.get(object);
- builder.append(fieldValue);
- } catch (final IllegalAccessException e) {
- // this can't happen. Would get a Security exception instead
- // throw a runtime exception in case the impossible happens.
- throw new InternalError("Unexpected IllegalAccessException");
- }
- }
- }
- } finally {
- unregister(object);
- }
- }
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
- * Object.
- *
- *
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- *
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
- * however this is not vital. Prime numbers are preferred, especially for the multiplier.
- *
- *
- * @param initialNonZeroOddNumber
- * a non-zero, odd number used as the initial value. This will be the returned
- * value if no fields are found to include in the hash code
- * @param multiplierNonZeroOddNumber
- * a non-zero, odd number used as the multiplier
- * @param object
- * the Object to create a hashCode for
- * @return int hash code
- * @throws IllegalArgumentException
- * if the Object is null
- * @throws IllegalArgumentException
- * if the number is zero or even
- *
- * @see HashCodeExclude
- */
- public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
- return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
- }
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * If the TestTransients parameter is set to true, transient members will be tested, otherwise they
- * are ignored, as they are likely derived fields, and not part of the value of the Object.
- *
- *
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- *
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
- * however this is not vital. Prime numbers are preferred, especially for the multiplier.
- *
- *
- * @param initialNonZeroOddNumber
- * a non-zero, odd number used as the initial value. This will be the returned
- * value if no fields are found to include in the hash code
- * @param multiplierNonZeroOddNumber
- * a non-zero, odd number used as the multiplier
- * @param object
- * the Object to create a hashCode for
- * @param testTransients
- * whether to include transient fields
- * @return int hash code
- * @throws IllegalArgumentException
- * if the Object is null
- * @throws IllegalArgumentException
- * if the number is zero or even
- *
- * @see HashCodeExclude
- */
- public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
- final boolean testTransients) {
- return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
- }
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * If the TestTransients parameter is set to true, transient members will be tested, otherwise they
- * are ignored, as they are likely derived fields, and not part of the value of the Object.
- *
- *
- *
- * Static fields will not be included. Superclass fields will be included up to and including the specified
- * superclass. A null superclass is treated as java.lang.Object.
- *
- *
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
- * however this is not vital. Prime numbers are preferred, especially for the multiplier.
- *
- *
- * @param
- * the type of the object involved
- * @param initialNonZeroOddNumber
- * a non-zero, odd number used as the initial value. This will be the returned
- * value if no fields are found to include in the hash code
- * @param multiplierNonZeroOddNumber
- * a non-zero, odd number used as the multiplier
- * @param object
- * the Object to create a hashCode for
- * @param testTransients
- * whether to include transient fields
- * @param reflectUpToClass
- * the superclass to reflect up to (inclusive), may be null
- * @param excludeFields
- * array of field names to exclude from use in calculation of hash code
- * @return int hash code
- * @throws IllegalArgumentException
- * if the Object is null
- * @throws IllegalArgumentException
- * if the number is zero or even
- *
- * @see HashCodeExclude
- * @since 2.0
- */
- public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
- final boolean testTransients, final Class super T> reflectUpToClass, final String... excludeFields) {
- Validate.isTrue(object != null, "The object to build a hash code for must not be null");
- final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
- Class> clazz = object.getClass();
- reflectionAppend(object, clazz, builder, testTransients, excludeFields);
- while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
- clazz = clazz.getSuperclass();
- reflectionAppend(object, clazz, builder, testTransients, excludeFields);
- }
- return builder.toHashCode();
- }
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * This constructor uses two hard coded choices for the constants needed to build a hash code.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * If the TestTransients parameter is set to true, transient members will be tested, otherwise they
- * are ignored, as they are likely derived fields, and not part of the value of the Object.
- *
- *
- *
- * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
- * in the hash code, the result of this method will be constant.
- *
- *
- * @param object
- * the Object to create a hashCode for
- * @param testTransients
- * whether to include transient fields
- * @return int hash code
- * @throws IllegalArgumentException
- * if the object is null
- *
- * @see HashCodeExclude
- */
- public static int reflectionHashCode(final Object object, final boolean testTransients) {
- return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
- testTransients, null);
- }
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * This constructor uses two hard coded choices for the constants needed to build a hash code.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
- * Object.
- *
- *
- *
- * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
- * in the hash code, the result of this method will be constant.
- *
- *
- * @param object
- * the Object to create a hashCode for
- * @param excludeFields
- * Collection of String field names to exclude from use in calculation of hash code
- * @return int hash code
- * @throws IllegalArgumentException
- * if the object is null
- *
- * @see HashCodeExclude
- */
- public static int reflectionHashCode(final Object object, final Collection excludeFields) {
- return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
- }
-
- // -------------------------------------------------------------------------
-
- /**
- *
- * Uses reflection to build a valid hash code from the fields of {@code object}.
- *
- *
- *
- * This constructor uses two hard coded choices for the constants needed to build a hash code.
- *
- *
- *
- * It uses AccessibleObject.setAccessible to gain access to private fields. This means that it will
- * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- *
- *
- * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
- * Object.
- *
- *
- *
- * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
- * in the hash code, the result of this method will be constant.
- *
- *
- * @param object
- * the Object to create a hashCode for
- * @param excludeFields
- * array of field names to exclude from use in calculation of hash code
- * @return int hash code
- * @throws IllegalArgumentException
- * if the object is null
- *
- * @see HashCodeExclude
- */
- public static int reflectionHashCode(final Object object, final String... excludeFields) {
- return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
- null, excludeFields);
- }
-
- /**
- *
- * Registers the given object. Used by the reflection methods to avoid infinite loops.
- *
- *
- * @param value
- * The object to register.
- */
- private static void register(final Object value) {
- Set registry = getRegistry();
- if (registry == null) {
- registry = new HashSet<>();
- REGISTRY.set(registry);
- }
- registry.add(new IDKey(value));
- }
-
- /**
- *
- * Unregisters the given object.
- *
- *
- *
- * Used by the reflection methods to avoid infinite loops.
- *
- * @param value
- * The object to unregister.
- * @since 2.3
- */
- private static void unregister(final Object value) {
- final Set registry = getRegistry();
- if (registry != null) {
- registry.remove(new IDKey(value));
- if (registry.isEmpty()) {
- REGISTRY.remove();
- }
- }
- }
-
- /**
- * Constant to use in building the hashCode.
- */
- private final int iConstant;
-
- /**
- * Running total of the hashCode.
- */
- private int iTotal = 0;
-
- /**
- *
- * Uses two hard coded choices for the constants needed to build a hashCode.
- *
- */
- public HashCodeBuilder() {
- iConstant = 37;
- iTotal = 17;
- }
-
- /**
- *
- * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
- * however this is not vital.
- *
- *
- *
- * Prime numbers are preferred, especially for the multiplier.
- *
- *
- * @param initialOddNumber
- * an odd number used as the initial value
- * @param multiplierOddNumber
- * an odd number used as the multiplier
- * @throws IllegalArgumentException
- * if the number is even
- */
- public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
- Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
- Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
- iConstant = multiplierOddNumber;
- iTotal = initialOddNumber;
- }
-
- /**
- *
- * Append a hashCode for a boolean.
- *
- *
- * This adds 1 when true, and 0 when false to the hashCode.
- *
- *
- * This is in contrast to the standard java.lang.Boolean.hashCode handling, which computes
- * a hashCode value of 1231 for java.lang.Boolean instances
- * that represent true or 1237 for java.lang.Boolean instances
- * that represent false.
- *
- *
- * This is in accordance with the Effective Java design.
- *
- *
- * @param value
- * the boolean to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final boolean value) {
- iTotal = iTotal * iConstant + (value ? 0 : 1);
- return this;
- }
-
- /**
- *
- * Append a hashCode for a boolean array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final boolean[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final boolean element : array) {
- append(element);
- }
- }
- return this;
- }
-
- // -------------------------------------------------------------------------
-
- /**
- *
- * Append a hashCode for a byte.
- *
- *
- * @param value
- * the byte to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final byte value) {
- iTotal = iTotal * iConstant + value;
- return this;
- }
-
- // -------------------------------------------------------------------------
-
- /**
- *
- * Append a hashCode for a byte array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final byte[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final byte element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for a char.
- *
- *
- * @param value
- * the char to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final char value) {
- iTotal = iTotal * iConstant + value;
- return this;
- }
-
- /**
- *
- * Append a hashCode for a char array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final char[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final char element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for a double.
- *
- *
- * @param value
- * the double to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final double value) {
- return append(Double.doubleToLongBits(value));
- }
-
- /**
- *
- * Append a hashCode for a double array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final double[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final double element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for a float.
- *
- *
- * @param value
- * the float to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final float value) {
- iTotal = iTotal * iConstant + Float.floatToIntBits(value);
- return this;
- }
-
- /**
- *
- * Append a hashCode for a float array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final float[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final float element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for an int.
- *
- *
- * @param value
- * the int to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final int value) {
- iTotal = iTotal * iConstant + value;
- return this;
- }
-
- /**
- *
- * Append a hashCode for an int array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final int[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final int element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for a long.
- *
- *
- * @param value
- * the long to add to the hashCode
- * @return this
- */
- // NOTE: This method uses >> and not >>> as Effective Java and
- // Long.hashCode do. Ideally we should switch to >>> at
- // some stage. There are backwards compat issues, so
- // that will have to wait for the time being. cf LANG-342.
- public HashCodeBuilder append(final long value) {
- iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
- return this;
- }
-
- /**
- *
- * Append a hashCode for a long array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final long[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final long element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for an Object.
- *
- *
- * @param object
- * the Object to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final Object object) {
- if (object == null) {
- iTotal = iTotal * iConstant;
-
- } else {
- if (object.getClass().isArray()) {
- // factor out array case in order to keep method small enough
- // to be inlined
- appendArray(object);
- } else {
- iTotal = iTotal * iConstant + object.hashCode();
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for an array.
- *
- *
- * @param object
- * the array to add to the hashCode
- */
- private void appendArray(final Object object) {
- // 'Switch' on type of array, to dispatch to the correct handler
- // This handles multi dimensional arrays
- if (object instanceof long[]) {
- append((long[]) object);
- } else if (object instanceof int[]) {
- append((int[]) object);
- } else if (object instanceof short[]) {
- append((short[]) object);
- } else if (object instanceof char[]) {
- append((char[]) object);
- } else if (object instanceof byte[]) {
- append((byte[]) object);
- } else if (object instanceof double[]) {
- append((double[]) object);
- } else if (object instanceof float[]) {
- append((float[]) object);
- } else if (object instanceof boolean[]) {
- append((boolean[]) object);
- } else {
- // Not an array of primitives
- append((Object[]) object);
- }
- }
-
- /**
- *
- * Append a hashCode for an Object array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final Object[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final Object element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Append a hashCode for a short.
- *
- *
- * @param value
- * the short to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final short value) {
- iTotal = iTotal * iConstant + value;
- return this;
- }
-
- /**
- *
- * Append a hashCode for a short array.
- *
- *
- * @param array
- * the array to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(final short[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (final short element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- *
- * Adds the result of super.hashCode() to this builder.
- *
- *
- * @param superHashCode
- * the result of calling super.hashCode()
- * @return this HashCodeBuilder, used to chain calls.
- * @since 2.0
- */
- public HashCodeBuilder appendSuper(final int superHashCode) {
- iTotal = iTotal * iConstant + superHashCode;
- return this;
- }
-
- /**
- *
- * Return the computed hashCode.
- *
- *
- * @return hashCode based on the fields appended
- */
- public int toHashCode() {
- return iTotal;
- }
-
- /**
- * Returns the computed hashCode.
- *
- * @return hashCode based on the fields appended
- *
- * @since 3.0
- */
- @Override
- public Integer build() {
- return Integer.valueOf(toHashCode());
- }
-
- /**
- *
- * The computed hashCode from toHashCode() is returned due to the likelihood
- * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
- * HashCodeBuilder itself is.
- *
- * @return hashCode based on the fields appended
- * @since 2.5
- */
- @Override
- public int hashCode() {
- return toHashCode();
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeExclude.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeExclude.java
deleted file mode 100644
index be1bac82..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/HashCodeExclude.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Use this annotation to exclude a field from being used by
- * the various reflectionHashcode methods defined on
- * {@link HashCodeBuilder}.
- *
- * @since 3.5
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface HashCodeExclude {
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/IDKey.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/IDKey.java
deleted file mode 100644
index 6e54a669..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/IDKey.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-// adapted from org.apache.axis.utils.IDKey
-
-/**
- * Wrap an identity key (System.identityHashCode())
- * so that an object can only be equal() to itself.
- *
- * This is necessary to disambiguate the occasional duplicate
- * identityHashCodes that can occur.
- */
-final class IDKey {
- private final Object value;
- private final int id;
-
- /**
- * Constructor for IDKey
- * @param _value The value
- */
- IDKey(final Object _value) {
- // This is the Object hash code
- id = System.identityHashCode(_value);
- // There have been some cases (LANG-459) that return the
- // same identity hash code for different objects. So
- // the value is also added to disambiguate these cases.
- value = _value;
- }
-
- /**
- * returns hash code - i.e. the system identity hashcode.
- * @return the hashcode
- */
- @Override
- public int hashCode() {
- return id;
- }
-
- /**
- * checks if instances are equal
- * @param other The other object to compare to
- * @return if the instances are for the same object
- */
- @Override
- public boolean equals(final Object other) {
- if (!(other instanceof IDKey)) {
- return false;
- }
- final IDKey idKey = (IDKey) other;
- if (id != idKey.id) {
- return false;
- }
- // Note that identity equals is used.
- return value == idKey.value;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Mutable.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Mutable.java
deleted file mode 100644
index 7846ec98..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Mutable.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-/**
- * Provides mutable access to a value.
- *
- * Mutable is used as a generic interface to the implementations in this package.
- *
- * A typical use case would be to enable a primitive or string to be passed to a method and allow that method to
- * effectively change the value of the primitive/string. Another use case is to store a frequently changing primitive in
- * a collection (for example a total in a map) without needing to create new Integer/Long wrapper objects.
- *
- * @param the type to set and get
- * @since 2.1
- */
-public interface Mutable {
-
- /**
- * Gets the value of this mutable.
- *
- * @return the stored value
- */
- T getValue();
-
- /**
- * Sets the value of this mutable.
- *
- * @param value
- * the value to store
- * @throws NullPointerException
- * if the object is null and null is invalid
- * @throws ClassCastException
- * if the type is invalid
- */
- void setValue(T value);
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableInt.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableInt.java
deleted file mode 100644
index b53bc9db..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableInt.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-/**
- * A mutable int wrapper.
- *
- * Note that as MutableInt does not extend Integer, it is not treated by String.format as an Integer parameter.
- *
- * @see Integer
- * @since 2.1
- */
-public class MutableInt extends Number implements Comparable, Mutable {
-
- /**
- * Required for serialization support.
- *
- * @see java.io.Serializable
- */
- private static final long serialVersionUID = 512176391864L;
-
- /** The mutable value. */
- private int value;
-
- /**
- * Constructs a new MutableInt with the default value of zero.
- */
- public MutableInt() {
- super();
- }
-
- /**
- * Constructs a new MutableInt with the specified value.
- *
- * @param value the initial value to store
- */
- public MutableInt(final int value) {
- super();
- this.value = value;
- }
-
- /**
- * Constructs a new MutableInt with the specified value.
- *
- * @param value the initial value to store, not null
- * @throws NullPointerException if the object is null
- */
- public MutableInt(final Number value) {
- super();
- this.value = value.intValue();
- }
-
- /**
- * Constructs a new MutableInt parsing the given string.
- *
- * @param value the string to parse, not null
- * @throws NumberFormatException if the string cannot be parsed into an int
- * @since 2.5
- */
- public MutableInt(final String value) {
- super();
- this.value = Integer.parseInt(value);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the value as a Integer instance.
- *
- * @return the value as a Integer, never null
- */
- @Override
- public Integer getValue() {
- return Integer.valueOf(this.value);
- }
-
- /**
- * Sets the value.
- *
- * @param value the value to set
- */
- public void setValue(final int value) {
- this.value = value;
- }
-
- /**
- * Sets the value from any Number instance.
- *
- * @param value the value to set, not null
- * @throws NullPointerException if the object is null
- */
- @Override
- public void setValue(final Number value) {
- this.value = value.intValue();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Increments the value.
- *
- * @since 2.2
- */
- public void increment() {
- value++;
- }
-
- /**
- * Increments this instance's value by 1; this method returns the value associated with the instance
- * immediately prior to the increment operation. This method is not thread safe.
- *
- * @return the value associated with the instance before it was incremented
- * @since 3.5
- */
- public int getAndIncrement() {
- final int last = value;
- value++;
- return last;
- }
-
- /**
- * Increments this instance's value by 1; this method returns the value associated with the instance
- * immediately after the increment operation. This method is not thread safe.
- *
- * @return the value associated with the instance after it is incremented
- * @since 3.5
- */
- public int incrementAndGet() {
- value++;
- return value;
- }
-
- /**
- * Decrements the value.
- *
- * @since 2.2
- */
- public void decrement() {
- value--;
- }
-
- /**
- * Decrements this instance's value by 1; this method returns the value associated with the instance
- * immediately prior to the decrement operation. This method is not thread safe.
- *
- * @return the value associated with the instance before it was decremented
- * @since 3.5
- */
- public int getAndDecrement() {
- final int last = value;
- value--;
- return last;
- }
-
- /**
- * Decrements this instance's value by 1; this method returns the value associated with the instance
- * immediately after the decrement operation. This method is not thread safe.
- *
- * @return the value associated with the instance after it is decremented
- * @since 3.5
- */
- public int decrementAndGet() {
- value--;
- return value;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Adds a value to the value of this instance.
- *
- * @param operand the value to add, not null
- * @since 2.2
- */
- public void add(final int operand) {
- this.value += operand;
- }
-
- /**
- * Adds a value to the value of this instance.
- *
- * @param operand the value to add, not null
- * @throws NullPointerException if the object is null
- * @since 2.2
- */
- public void add(final Number operand) {
- this.value += operand.intValue();
- }
-
- /**
- * Subtracts a value from the value of this instance.
- *
- * @param operand the value to subtract, not null
- * @since 2.2
- */
- public void subtract(final int operand) {
- this.value -= operand;
- }
-
- /**
- * Subtracts a value from the value of this instance.
- *
- * @param operand the value to subtract, not null
- * @throws NullPointerException if the object is null
- * @since 2.2
- */
- public void subtract(final Number operand) {
- this.value -= operand.intValue();
- }
-
- /**
- * Increments this instance's value by {@code operand}; this method returns the value associated with the instance
- * immediately after the addition operation. This method is not thread safe.
- *
- * @param operand the quantity to add, not null
- * @return the value associated with this instance after adding the operand
- * @since 3.5
- */
- public int addAndGet(final int operand) {
- this.value += operand;
- return value;
- }
-
- /**
- * Increments this instance's value by {@code operand}; this method returns the value associated with the instance
- * immediately after the addition operation. This method is not thread safe.
- *
- * @param operand the quantity to add, not null
- * @throws NullPointerException if {@code operand} is null
- * @return the value associated with this instance after adding the operand
- * @since 3.5
- */
- public int addAndGet(final Number operand) {
- this.value += operand.intValue();
- return value;
- }
-
- /**
- * Increments this instance's value by {@code operand}; this method returns the value associated with the instance
- * immediately prior to the addition operation. This method is not thread safe.
- *
- * @param operand the quantity to add, not null
- * @return the value associated with this instance immediately before the operand was added
- * @since 3.5
- */
- public int getAndAdd(final int operand) {
- final int last = value;
- this.value += operand;
- return last;
- }
-
- /**
- * Increments this instance's value by {@code operand}; this method returns the value associated with the instance
- * immediately prior to the addition operation. This method is not thread safe.
- *
- * @param operand the quantity to add, not null
- * @throws NullPointerException if {@code operand} is null
- * @return the value associated with this instance immediately before the operand was added
- * @since 3.5
- */
- public int getAndAdd(final Number operand) {
- final int last = value;
- this.value += operand.intValue();
- return last;
- }
-
- //-----------------------------------------------------------------------
- // shortValue and byteValue rely on Number implementation
- /**
- * Returns the value of this MutableInt as an int.
- *
- * @return the numeric value represented by this object after conversion to type int.
- */
- @Override
- public int intValue() {
- return value;
- }
-
- /**
- * Returns the value of this MutableInt as a long.
- *
- * @return the numeric value represented by this object after conversion to type long.
- */
- @Override
- public long longValue() {
- return value;
- }
-
- /**
- * Returns the value of this MutableInt as a float.
- *
- * @return the numeric value represented by this object after conversion to type float.
- */
- @Override
- public float floatValue() {
- return value;
- }
-
- /**
- * Returns the value of this MutableInt as a double.
- *
- * @return the numeric value represented by this object after conversion to type double.
- */
- @Override
- public double doubleValue() {
- return value;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets this mutable as an instance of Integer.
- *
- * @return a Integer instance containing the value from this mutable, never null
- */
- public Integer toInteger() {
- return Integer.valueOf(intValue());
- }
-
- //-----------------------------------------------------------------------
- /**
- * Compares this object to the specified object. The result is true if and only if the argument is
- * not null and is a MutableInt object that contains the same int value
- * as this object.
- *
- * @param obj the object to compare with, null returns false
- * @return true if the objects are the same; false otherwise.
- */
- @Override
- public boolean equals(final Object obj) {
- if (obj instanceof MutableInt) {
- return value == ((MutableInt) obj).intValue();
- }
- return false;
- }
-
- /**
- * Returns a suitable hash code for this mutable.
- *
- * @return a suitable hash code
- */
- @Override
- public int hashCode() {
- return value;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Compares this mutable to another in ascending order.
- *
- * @param other the other mutable to compare to, not null
- * @return negative if this is less, zero if equal, positive if greater
- */
- @Override
- public int compareTo(final MutableInt other) {
- return NumberUtils.compare(this.value, other.value);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the String value of this mutable.
- *
- * @return the mutable value as a string
- */
- @Override
- public String toString() {
- return String.valueOf(value);
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableObject.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableObject.java
deleted file mode 100644
index 20226755..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/MutableObject.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-import java.io.Serializable;
-
-/**
- * A mutable Object wrapper.
- *
- * @param the type to set and get
- * @since 2.1
- */
-public class MutableObject implements Mutable, Serializable {
-
- /**
- * Required for serialization support.
- *
- * @see Serializable
- */
- private static final long serialVersionUID = 86241875189L;
-
- /** The mutable value. */
- private T value;
-
- /**
- * Constructs a new MutableObject with the default value of null.
- */
- public MutableObject() {
- super();
- }
-
- /**
- * Constructs a new MutableObject with the specified value.
- *
- * @param value the initial value to store
- */
- public MutableObject(final T value) {
- super();
- this.value = value;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the value.
- *
- * @return the value, may be null
- */
- @Override
- public T getValue() {
- return this.value;
- }
-
- /**
- * Sets the value.
- *
- * @param value the value to set
- */
- @Override
- public void setValue(final T value) {
- this.value = value;
- }
-
- //-----------------------------------------------------------------------
- /**
- *
- * Compares this object against the specified object. The result is true if and only if the argument
- * is not null and is a MutableObject object that contains the same T
- * value as this object.
- *
- *
- * @param obj the object to compare with, null returns false
- * @return true if the objects are the same;
- * true if the objects have equivalent value fields;
- * false otherwise.
- */
- @Override
- public boolean equals(final Object obj) {
- if (obj == null) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- if (this.getClass() == obj.getClass()) {
- final MutableObject> that = (MutableObject>) obj;
- return this.value.equals(that.value);
- }
- return false;
- }
-
- /**
- * Returns the value's hash code or 0 if the value is null.
- *
- * @return the value's hash code or 0 if the value is null.
- */
- @Override
- public int hashCode() {
- return value == null ? 0 : value.hashCode();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Returns the String value of this mutable.
- *
- * @return the mutable value as a string
- */
- @Override
- public String toString() {
- return value == null ? "null" : value.toString();
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/NumberUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/NumberUtils.java
deleted file mode 100644
index 4af2089d..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/NumberUtils.java
+++ /dev/null
@@ -1,1823 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-import java.lang.reflect.Array;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.math.RoundingMode;
-
-/**
- * Provides extra functionality for Java Number classes.
- *
- * @since 2.0
- */
-public class NumberUtils {
-
- /** Reusable Long constant for zero. */
- public static final Long LONG_ZERO = Long.valueOf(0L);
- /** Reusable Long constant for one. */
- public static final Long LONG_ONE = Long.valueOf(1L);
- /** Reusable Long constant for minus one. */
- public static final Long LONG_MINUS_ONE = Long.valueOf(-1L);
- /** Reusable Integer constant for zero. */
- public static final Integer INTEGER_ZERO = Integer.valueOf(0);
- /** Reusable Integer constant for one. */
- public static final Integer INTEGER_ONE = Integer.valueOf(1);
- /** Reusable Integer constant for two */
- public static final Integer INTEGER_TWO = Integer.valueOf(2);
- /** Reusable Integer constant for minus one. */
- public static final Integer INTEGER_MINUS_ONE = Integer.valueOf(-1);
- /** Reusable Short constant for zero. */
- public static final Short SHORT_ZERO = Short.valueOf((short) 0);
- /** Reusable Short constant for one. */
- public static final Short SHORT_ONE = Short.valueOf((short) 1);
- /** Reusable Short constant for minus one. */
- public static final Short SHORT_MINUS_ONE = Short.valueOf((short) -1);
- /** Reusable Byte constant for zero. */
- public static final Byte BYTE_ZERO = Byte.valueOf((byte) 0);
- /** Reusable Byte constant for one. */
- public static final Byte BYTE_ONE = Byte.valueOf((byte) 1);
- /** Reusable Byte constant for minus one. */
- public static final Byte BYTE_MINUS_ONE = Byte.valueOf((byte) -1);
- /** Reusable Double constant for zero. */
- public static final Double DOUBLE_ZERO = Double.valueOf(0.0d);
- /** Reusable Double constant for one. */
- public static final Double DOUBLE_ONE = Double.valueOf(1.0d);
- /** Reusable Double constant for minus one. */
- public static final Double DOUBLE_MINUS_ONE = Double.valueOf(-1.0d);
- /** Reusable Float constant for zero. */
- public static final Float FLOAT_ZERO = Float.valueOf(0.0f);
- /** Reusable Float constant for one. */
- public static final Float FLOAT_ONE = Float.valueOf(1.0f);
- /** Reusable Float constant for minus one. */
- public static final Float FLOAT_MINUS_ONE = Float.valueOf(-1.0f);
-
-
- /**
- * NumberUtils instances should NOT be constructed in standard programming.
- * Instead, the class should be used as NumberUtils.toInt("6");.
- *
- * This constructor is public to permit tools that require a JavaBean instance
- * to operate.
- */
- public NumberUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Convert a String to an int, returning
- * zero if the conversion fails.
- *
- * If the string is null, zero is returned.
- *
- *
- * NumberUtils.toInt(null) = 0
- * NumberUtils.toInt("") = 0
- * NumberUtils.toInt("1") = 1
- *
- *
- * @param str the string to convert, may be null
- * @return the int represented by the string, or zero if
- * conversion fails
- * @since 2.1
- */
- public static int toInt(final String str) {
- return toInt(str, 0);
- }
-
- /**
- * Convert a String to an int, returning a
- * default value if the conversion fails.
- *
- * If the string is null, the default value is returned.
- *
- *
- * NumberUtils.toInt(null, 1) = 1
- * NumberUtils.toInt("", 1) = 1
- * NumberUtils.toInt("1", 0) = 1
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the int represented by the string, or the default if conversion fails
- * @since 2.1
- */
- public static int toInt(final String str, final int defaultValue) {
- if(str == null) {
- return defaultValue;
- }
- try {
- return Integer.parseInt(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a String to a long, returning
- * zero if the conversion fails.
- *
- * If the string is null, zero is returned.
- *
- *
- * NumberUtils.toLong(null) = 0L
- * NumberUtils.toLong("") = 0L
- * NumberUtils.toLong("1") = 1L
- *
- *
- * @param str the string to convert, may be null
- * @return the long represented by the string, or 0 if
- * conversion fails
- * @since 2.1
- */
- public static long toLong(final String str) {
- return toLong(str, 0L);
- }
-
- /**
- * Convert a String to a long, returning a
- * default value if the conversion fails.
- *
- * If the string is null, the default value is returned.
- *
- *
- * NumberUtils.toLong(null, 1L) = 1L
- * NumberUtils.toLong("", 1L) = 1L
- * NumberUtils.toLong("1", 0L) = 1L
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the long represented by the string, or the default if conversion fails
- * @since 2.1
- */
- public static long toLong(final String str, final long defaultValue) {
- if (str == null) {
- return defaultValue;
- }
- try {
- return Long.parseLong(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a String to a float, returning
- * 0.0f if the conversion fails.
- *
- * If the string str is null,
- * 0.0f is returned.
- *
- *
- * NumberUtils.toFloat(null) = 0.0f
- * NumberUtils.toFloat("") = 0.0f
- * NumberUtils.toFloat("1.5") = 1.5f
- *
- *
- * @param str the string to convert, may be null
- * @return the float represented by the string, or 0.0f
- * if conversion fails
- * @since 2.1
- */
- public static float toFloat(final String str) {
- return toFloat(str, 0.0f);
- }
-
- /**
- * Convert a String to a float, returning a
- * default value if the conversion fails.
- *
- * If the string str is null, the default
- * value is returned.
- *
- *
- * NumberUtils.toFloat(null, 1.1f) = 1.0f
- * NumberUtils.toFloat("", 1.1f) = 1.1f
- * NumberUtils.toFloat("1.5", 0.0f) = 1.5f
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the float represented by the string, or defaultValue
- * if conversion fails
- * @since 2.1
- */
- public static float toFloat(final String str, final float defaultValue) {
- if (str == null) {
- return defaultValue;
- }
- try {
- return Float.parseFloat(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a String to a double, returning
- * 0.0d if the conversion fails.
- *
- * If the string str is null,
- * 0.0d is returned.
- *
- *
- * NumberUtils.toDouble(null) = 0.0d
- * NumberUtils.toDouble("") = 0.0d
- * NumberUtils.toDouble("1.5") = 1.5d
- *
- *
- * @param str the string to convert, may be null
- * @return the double represented by the string, or 0.0d
- * if conversion fails
- * @since 2.1
- */
- public static double toDouble(final String str) {
- return toDouble(str, 0.0d);
- }
-
- /**
- * Convert a String to a double, returning a
- * default value if the conversion fails.
- *
- * If the string str is null, the default
- * value is returned.
- *
- *
- * NumberUtils.toDouble(null, 1.1d) = 1.1d
- * NumberUtils.toDouble("", 1.1d) = 1.1d
- * NumberUtils.toDouble("1.5", 0.0d) = 1.5d
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the double represented by the string, or defaultValue
- * if conversion fails
- * @since 2.1
- */
- public static double toDouble(final String str, final double defaultValue) {
- if (str == null) {
- return defaultValue;
- }
- try {
- return Double.parseDouble(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a BigDecimal to a double.
- *
- * If the BigDecimal value is
- * null, then the specified default value is returned.
- *
- *
- * NumberUtils.toDouble(null) = 0.0d
- * NumberUtils.toDouble(BigDecimal.valudOf(8.5d)) = 8.5d
- *
- *
- * @param value the BigDecimal to convert, may be null.
- * @return the double represented by the BigDecimal or
- * 0.0d if the BigDecimal is null.
- * @since 3.8
- */
- public static double toDouble(final BigDecimal value) {
- return toDouble(value, 0.0d);
- }
-
- /**
- * Convert a BigDecimal to a double.
- *
- * If the BigDecimal value is
- * null, then the specified default value is returned.
- *
- *
- * NumberUtils.toDouble(null, 1.1d) = 1.1d
- * NumberUtils.toDouble(BigDecimal.valudOf(8.5d), 1.1d) = 8.5d
- *
- *
- * @param value the BigDecimal to convert, may be null.
- * @param defaultValue the default value
- * @return the double represented by the BigDecimal or the
- * defaultValue if the BigDecimal is null.
- * @since 3.8
- */
- public static double toDouble(final BigDecimal value, final double defaultValue) {
- return value == null ? defaultValue : value.doubleValue();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Convert a String to a byte, returning
- * zero if the conversion fails.
- *
- * If the string is null, zero is returned.
- *
- *
- * NumberUtils.toByte(null) = 0
- * NumberUtils.toByte("") = 0
- * NumberUtils.toByte("1") = 1
- *
- *
- * @param str the string to convert, may be null
- * @return the byte represented by the string, or zero if
- * conversion fails
- * @since 2.5
- */
- public static byte toByte(final String str) {
- return toByte(str, (byte) 0);
- }
-
- /**
- * Convert a String to a byte, returning a
- * default value if the conversion fails.
- *
- * If the string is null, the default value is returned.
- *
- *
- * NumberUtils.toByte(null, 1) = 1
- * NumberUtils.toByte("", 1) = 1
- * NumberUtils.toByte("1", 0) = 1
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the byte represented by the string, or the default if conversion fails
- * @since 2.5
- */
- public static byte toByte(final String str, final byte defaultValue) {
- if(str == null) {
- return defaultValue;
- }
- try {
- return Byte.parseByte(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a String to a short, returning
- * zero if the conversion fails.
- *
- * If the string is null, zero is returned.
- *
- *
- * NumberUtils.toShort(null) = 0
- * NumberUtils.toShort("") = 0
- * NumberUtils.toShort("1") = 1
- *
- *
- * @param str the string to convert, may be null
- * @return the short represented by the string, or zero if
- * conversion fails
- * @since 2.5
- */
- public static short toShort(final String str) {
- return toShort(str, (short) 0);
- }
-
- /**
- * Convert a String to an short, returning a
- * default value if the conversion fails.
- *
- * If the string is null, the default value is returned.
- *
- *
- * NumberUtils.toShort(null, 1) = 1
- * NumberUtils.toShort("", 1) = 1
- * NumberUtils.toShort("1", 0) = 1
- *
- *
- * @param str the string to convert, may be null
- * @param defaultValue the default value
- * @return the short represented by the string, or the default if conversion fails
- * @since 2.5
- */
- public static short toShort(final String str, final short defaultValue) {
- if(str == null) {
- return defaultValue;
- }
- try {
- return Short.parseShort(str);
- } catch (final NumberFormatException nfe) {
- return defaultValue;
- }
- }
-
- /**
- * Convert a BigDecimal to a BigDecimal with a scale of
- * two that has been rounded using RoundingMode.HALF_EVEN. If the supplied
- * value is null, then BigDecimal.ZERO is returned.
- *
- * Note, the scale of a BigDecimal is the number of digits to the right of the
- * decimal point.
- *
- * @param value the BigDecimal to convert, may be null.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final BigDecimal value) {
- return toScaledBigDecimal(value, INTEGER_TWO, RoundingMode.HALF_EVEN);
- }
-
- /**
- * Convert a BigDecimal to a BigDecimal whose scale is the
- * specified value with a RoundingMode applied. If the input value
- * is null, we simply return BigDecimal.ZERO.
- *
- * @param value the BigDecimal to convert, may be null.
- * @param scale the number of digits to the right of the decimal point.
- * @param roundingMode a rounding behavior for numerical operations capable of
- * discarding precision.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final BigDecimal value, final int scale, final RoundingMode roundingMode) {
- if (value == null) {
- return BigDecimal.ZERO;
- }
- return value.setScale(
- scale,
- (roundingMode == null) ? RoundingMode.HALF_EVEN : roundingMode
- );
- }
-
- /**
- * Convert a Float to a BigDecimal with a scale of
- * two that has been rounded using RoundingMode.HALF_EVEN. If the supplied
- * value is null, then BigDecimal.ZERO is returned.
- *
- * Note, the scale of a BigDecimal is the number of digits to the right of the
- * decimal point.
- *
- * @param value the Float to convert, may be null.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final Float value) {
- return toScaledBigDecimal(value, INTEGER_TWO, RoundingMode.HALF_EVEN);
- }
-
- /**
- * Convert a Float to a BigDecimal whose scale is the
- * specified value with a RoundingMode applied. If the input value
- * is null, we simply return BigDecimal.ZERO.
- *
- * @param value the Float to convert, may be null.
- * @param scale the number of digits to the right of the decimal point.
- * @param roundingMode a rounding behavior for numerical operations capable of
- * discarding precision.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final Float value, final int scale, final RoundingMode roundingMode) {
- if (value == null) {
- return BigDecimal.ZERO;
- }
- return toScaledBigDecimal(
- BigDecimal.valueOf(value),
- scale,
- roundingMode
- );
- }
-
- /**
- * Convert a Double to a BigDecimal with a scale of
- * two that has been rounded using RoundingMode.HALF_EVEN. If the supplied
- * value is null, then BigDecimal.ZERO is returned.
- *
- * Note, the scale of a BigDecimal is the number of digits to the right of the
- * decimal point.
- *
- * @param value the Double to convert, may be null.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final Double value) {
- return toScaledBigDecimal(value, INTEGER_TWO, RoundingMode.HALF_EVEN);
- }
-
- /**
- * Convert a Double to a BigDecimal whose scale is the
- * specified value with a RoundingMode applied. If the input value
- * is null, we simply return BigDecimal.ZERO.
- *
- * @param value the Double to convert, may be null.
- * @param scale the number of digits to the right of the decimal point.
- * @param roundingMode a rounding behavior for numerical operations capable of
- * discarding precision.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final Double value, final int scale, final RoundingMode roundingMode) {
- if (value == null) {
- return BigDecimal.ZERO;
- }
- return toScaledBigDecimal(
- BigDecimal.valueOf(value),
- scale,
- roundingMode
- );
- }
-
- /**
- * Convert a String to a BigDecimal with a scale of
- * two that has been rounded using RoundingMode.HALF_EVEN. If the supplied
- * value is null, then BigDecimal.ZERO is returned.
- *
- * Note, the scale of a BigDecimal is the number of digits to the right of the
- * decimal point.
- *
- * @param value the String to convert, may be null.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final String value) {
- return toScaledBigDecimal(value, INTEGER_TWO, RoundingMode.HALF_EVEN);
- }
-
- /**
- * Convert a String to a BigDecimal whose scale is the
- * specified value with a RoundingMode applied. If the input value
- * is null, we simply return BigDecimal.ZERO.
- *
- * @param value the String to convert, may be null.
- * @param scale the number of digits to the right of the decimal point.
- * @param roundingMode a rounding behavior for numerical operations capable of
- * discarding precision.
- * @return the scaled, with appropriate rounding, BigDecimal.
- * @since 3.8
- */
- public static BigDecimal toScaledBigDecimal(final String value, final int scale, final RoundingMode roundingMode) {
- if (value == null) {
- return BigDecimal.ZERO;
- }
- return toScaledBigDecimal(
- createBigDecimal(value),
- scale,
- roundingMode
- );
- }
-
- //-----------------------------------------------------------------------
- // must handle Long, Float, Integer, Float, Short,
- // BigDecimal, BigInteger and Byte
- // useful methods:
- // Byte.decode(String)
- // Byte.valueOf(String,int radix)
- // Byte.valueOf(String)
- // Double.valueOf(String)
- // Float.valueOf(String)
- // Float.valueOf(String)
- // Integer.valueOf(String,int radix)
- // Integer.valueOf(String)
- // Integer.decode(String)
- // Integer.getInteger(String)
- // Integer.getInteger(String,int val)
- // Integer.getInteger(String,Integer val)
- // Integer.valueOf(String)
- // Double.valueOf(String)
- // new Byte(String)
- // Long.valueOf(String)
- // Long.getLong(String)
- // Long.getLong(String,int)
- // Long.getLong(String,Integer)
- // Long.valueOf(String,int)
- // Long.valueOf(String)
- // Short.valueOf(String)
- // Short.decode(String)
- // Short.valueOf(String,int)
- // Short.valueOf(String)
- // new BigDecimal(String)
- // new BigInteger(String)
- // new BigInteger(String,int radix)
- // Possible inputs:
- // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
- // plus minus everything. Prolly more. A lot are not separable.
-
- /**
- * Turns a string value into a java.lang.Number.
- *
- * If the string starts with {@code 0x} or {@code -0x} (lower or upper case) or {@code #} or {@code -#}, it
- * will be interpreted as a hexadecimal Integer - or Long, if the number of digits after the
- * prefix is more than 8 - or BigInteger if there are more than 16 digits.
- *
- * Then, the value is examined for a type qualifier on the end, i.e. one of
- * 'f','F','d','D','l','L'. If it is found, it starts
- * trying to create successively larger types from the type specified
- * until one is found that can represent the value.
- *
- * If a type specifier is not found, it will check for a decimal point
- * and then try successively larger types from Integer to
- * BigInteger and from Float to
- * BigDecimal.
- *
- *
- * Integral values with a leading {@code 0} will be interpreted as octal; the returned number will
- * be Integer, Long or BigDecimal as appropriate.
- *
- *
- * Returns null if the string is null.
- *
- * This method does not trim the input string, i.e., strings with leading
- * or trailing spaces will generate NumberFormatExceptions.
- *
- * @param str String containing a number, may be null
- * @return Number created from the string (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static Number createNumber(final String str) {
- if (str == null) {
- return null;
- }
- if (StringUtils.isBlank(str)) {
- throw new NumberFormatException("A blank string is not a valid number");
- }
- // Need to deal with all possible hex prefixes here
- final String[] hex_prefixes = {"0x", "0X", "-0x", "-0X", "#", "-#"};
- int pfxLen = 0;
- for(final String pfx : hex_prefixes) {
- if (str.startsWith(pfx)) {
- pfxLen += pfx.length();
- break;
- }
- }
- if (pfxLen > 0) { // we have a hex number
- char firstSigDigit = 0; // strip leading zeroes
- for(int i = pfxLen; i < str.length(); i++) {
- firstSigDigit = str.charAt(i);
- if (firstSigDigit == '0') { // count leading zeroes
- pfxLen++;
- } else {
- break;
- }
- }
- final int hexDigits = str.length() - pfxLen;
- if (hexDigits > 16 || hexDigits == 16 && firstSigDigit > '7') { // too many for Long
- return createBigInteger(str);
- }
- if (hexDigits > 8 || hexDigits == 8 && firstSigDigit > '7') { // too many for an int
- return createLong(str);
- }
- return createInteger(str);
- }
- final char lastChar = str.charAt(str.length() - 1);
- String mant;
- String dec;
- String exp;
- final int decPos = str.indexOf('.');
- final int expPos = str.indexOf('e') + str.indexOf('E') + 1; // assumes both not present
- // if both e and E are present, this is caught by the checks on expPos (which prevent IOOBE)
- // and the parsing which will detect if e or E appear in a number due to using the wrong offset
-
- if (decPos > -1) { // there is a decimal point
- if (expPos > -1) { // there is an exponent
- if (expPos < decPos || expPos > str.length()) { // prevents double exponent causing IOOBE
- throw new NumberFormatException(str + " is not a valid number.");
- }
- dec = str.substring(decPos + 1, expPos);
- } else {
- dec = str.substring(decPos + 1);
- }
- mant = getMantissa(str, decPos);
- } else {
- if (expPos > -1) {
- if (expPos > str.length()) { // prevents double exponent causing IOOBE
- throw new NumberFormatException(str + " is not a valid number.");
- }
- mant = getMantissa(str, expPos);
- } else {
- mant = getMantissa(str);
- }
- dec = null;
- }
- if (!Character.isDigit(lastChar) && lastChar != '.') {
- if (expPos > -1 && expPos < str.length() - 1) {
- exp = str.substring(expPos + 1, str.length() - 1);
- } else {
- exp = null;
- }
- //Requesting a specific type..
- final String numeric = str.substring(0, str.length() - 1);
- final boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
- switch (lastChar) {
- case 'l' :
- case 'L' :
- if (dec == null
- && exp == null
- && (!numeric.isEmpty() && numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
- try {
- return createLong(numeric);
- } catch (final NumberFormatException nfe) { // NOPMD
- // Too big for a long
- }
- return createBigInteger(numeric);
-
- }
- throw new NumberFormatException(str + " is not a valid number.");
- case 'f' :
- case 'F' :
- try {
- final Float f = createFloat(str);
- if (!(f.isInfinite() || f.floatValue() == 0.0F && !allZeros)) {
- //If it's too big for a float or the float value = 0 and the string
- //has non-zeros in it, then float does not have the precision we want
- return f;
- }
-
- } catch (final NumberFormatException nfe) { // NOPMD
- // ignore the bad number
- }
- //$FALL-THROUGH$
- case 'd' :
- case 'D' :
- try {
- final Double d = createDouble(str);
- if (!(d.isInfinite() || d.floatValue() == 0.0D && !allZeros)) {
- return d;
- }
- } catch (final NumberFormatException nfe) { // NOPMD
- // ignore the bad number
- }
- try {
- return createBigDecimal(numeric);
- } catch (final NumberFormatException e) { // NOPMD
- // ignore the bad number
- }
- //$FALL-THROUGH$
- default :
- throw new NumberFormatException(str + " is not a valid number.");
-
- }
- }
- //User doesn't have a preference on the return type, so let's start
- //small and go from there...
- if (expPos > -1 && expPos < str.length() - 1) {
- exp = str.substring(expPos + 1, str.length());
- } else {
- exp = null;
- }
- if (dec == null && exp == null) { // no decimal point and no exponent
- //Must be an Integer, Long, Biginteger
- try {
- return createInteger(str);
- } catch (final NumberFormatException nfe) { // NOPMD
- // ignore the bad number
- }
- try {
- return createLong(str);
- } catch (final NumberFormatException nfe) { // NOPMD
- // ignore the bad number
- }
- return createBigInteger(str);
- }
-
- //Must be a Float, Double, BigDecimal
- final boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
- try {
- final Float f = createFloat(str);
- final Double d = createDouble(str);
- if (!f.isInfinite()
- && !(f.floatValue() == 0.0F && !allZeros)
- && f.toString().equals(d.toString())) {
- return f;
- }
- if (!d.isInfinite() && !(d.doubleValue() == 0.0D && !allZeros)) {
- final BigDecimal b = createBigDecimal(str);
- if (b.compareTo(BigDecimal.valueOf(d.doubleValue())) == 0) {
- return d;
- }
- return b;
- }
- } catch (final NumberFormatException nfe) { // NOPMD
- // ignore the bad number
- }
- return createBigDecimal(str);
- }
-
- /**
- * Utility method for {@link #createNumber(String)}.
- *
- * Returns mantissa of the given number.
- *
- * @param str the string representation of the number
- * @return mantissa of the given number
- */
- private static String getMantissa(final String str) {
- return getMantissa(str, str.length());
- }
-
- /**
- * Utility method for {@link #createNumber(String)}.
- *
- * Returns mantissa of the given number.
- *
- * @param str the string representation of the number
- * @param stopPos the position of the exponent or decimal point
- * @return mantissa of the given number
- */
- private static String getMantissa(final String str, final int stopPos) {
- final char firstChar = str.charAt(0);
- final boolean hasSign = firstChar == '-' || firstChar == '+';
-
- return hasSign ? str.substring(1, stopPos) : str.substring(0, stopPos);
- }
-
- /**
- * Utility method for {@link #createNumber(String)}.
- *
- * Returns true if s is null.
- *
- * @param str the String to check
- * @return if it is all zeros or null
- */
- private static boolean isAllZeros(final String str) {
- if (str == null) {
- return true;
- }
- for (int i = str.length() - 1; i >= 0; i--) {
- if (str.charAt(i) != '0') {
- return false;
- }
- }
- return !str.isEmpty();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Convert a String to a Float.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted Float (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static Float createFloat(final String str) {
- if (str == null) {
- return null;
- }
- return Float.valueOf(str);
- }
-
- /**
- * Convert a String to a Double.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted Double (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static Double createDouble(final String str) {
- if (str == null) {
- return null;
- }
- return Double.valueOf(str);
- }
-
- /**
- * Convert a String to a Integer, handling
- * hex (0xhhhh) and octal (0dddd) notations.
- * N.B. a leading zero means octal; spaces are not trimmed.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted Integer (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static Integer createInteger(final String str) {
- if (str == null) {
- return null;
- }
- // decode() handles 0xAABD and 0777 (hex and octal) as well.
- return Integer.decode(str);
- }
-
- /**
- * Convert a String to a Long;
- * since 3.1 it handles hex (0Xhhhh) and octal (0ddd) notations.
- * N.B. a leading zero means octal; spaces are not trimmed.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted Long (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static Long createLong(final String str) {
- if (str == null) {
- return null;
- }
- return Long.decode(str);
- }
-
- /**
- * Convert a String to a BigInteger;
- * since 3.2 it handles hex (0x or #) and octal (0) notations.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted BigInteger (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static BigInteger createBigInteger(final String str) {
- if (str == null) {
- return null;
- }
- int pos = 0; // offset within string
- int radix = 10;
- boolean negate = false; // need to negate later?
- if (str.startsWith("-")) {
- negate = true;
- pos = 1;
- }
- if (str.startsWith("0x", pos) || str.startsWith("0X", pos)) { // hex
- radix = 16;
- pos += 2;
- } else if (str.startsWith("#", pos)) { // alternative hex (allowed by Long/Integer)
- radix = 16;
- pos ++;
- } else if (str.startsWith("0", pos) && str.length() > pos + 1) { // octal; so long as there are additional digits
- radix = 8;
- pos ++;
- } // default is to treat as decimal
-
- final BigInteger value = new BigInteger(str.substring(pos), radix);
- return negate ? value.negate() : value;
- }
-
- /**
- * Convert a String to a BigDecimal.
- *
- * Returns null if the string is null.
- *
- * @param str a String to convert, may be null
- * @return converted BigDecimal (or null if the input is null)
- * @throws NumberFormatException if the value cannot be converted
- */
- public static BigDecimal createBigDecimal(final String str) {
- if (str == null) {
- return null;
- }
- // handle JDK1.3.1 bug where "" throws IndexOutOfBoundsException
- if (StringUtils.isBlank(str)) {
- throw new NumberFormatException("A blank string is not a valid number");
- }
- if (str.trim().startsWith("--")) {
- // this is protection for poorness in java.lang.BigDecimal.
- // it accepts this as a legal value, but it does not appear
- // to be in specification of class. OS X Java parses it to
- // a wrong value.
- throw new NumberFormatException(str + " is not a valid number.");
- }
- return new BigDecimal(str);
- }
-
- // Min in array
- //--------------------------------------------------------------------
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from min(long[]) to min(long...)
- */
- public static long min(final long... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- long min = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] < min) {
- min = array[i];
- }
- }
-
- return min;
- }
-
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from min(int[]) to min(int...)
- */
- public static int min(final int... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- int min = array[0];
- for (int j = 1; j < array.length; j++) {
- if (array[j] < min) {
- min = array[j];
- }
- }
-
- return min;
- }
-
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from min(short[]) to min(short...)
- */
- public static short min(final short... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- short min = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] < min) {
- min = array[i];
- }
- }
-
- return min;
- }
-
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from min(byte[]) to min(byte...)
- */
- public static byte min(final byte... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- byte min = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] < min) {
- min = array[i];
- }
- }
-
- return min;
- }
-
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @see IEEE754rUtils#min(double[]) IEEE754rUtils for a version of this method that handles NaN differently
- * @since 3.4 Changed signature from min(double[]) to min(double...)
- */
- public static double min(final double... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- double min = array[0];
- for (int i = 1; i < array.length; i++) {
- if (Double.isNaN(array[i])) {
- return Double.NaN;
- }
- if (array[i] < min) {
- min = array[i];
- }
- }
-
- return min;
- }
-
- /**
- * Returns the minimum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the minimum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @see IEEE754rUtils#min(float[]) IEEE754rUtils for a version of this method that handles NaN differently
- * @since 3.4 Changed signature from min(float[]) to min(float...)
- */
- public static float min(final float... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns min
- float min = array[0];
- for (int i = 1; i < array.length; i++) {
- if (Float.isNaN(array[i])) {
- return Float.NaN;
- }
- if (array[i] < min) {
- min = array[i];
- }
- }
-
- return min;
- }
-
- // Max in array
- //--------------------------------------------------------------------
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from max(long[]) to max(long...)
- */
- public static long max(final long... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- long max = array[0];
- for (int j = 1; j < array.length; j++) {
- if (array[j] > max) {
- max = array[j];
- }
- }
-
- return max;
- }
-
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from max(int[]) to max(int...)
- */
- public static int max(final int... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- int max = array[0];
- for (int j = 1; j < array.length; j++) {
- if (array[j] > max) {
- max = array[j];
- }
- }
-
- return max;
- }
-
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from max(short[]) to max(short...)
- */
- public static short max(final short... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- short max = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] > max) {
- max = array[i];
- }
- }
-
- return max;
- }
-
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @since 3.4 Changed signature from max(byte[]) to max(byte...)
- */
- public static byte max(final byte... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- byte max = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] > max) {
- max = array[i];
- }
- }
-
- return max;
- }
-
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @see IEEE754rUtils#max(double[]) IEEE754rUtils for a version of this method that handles NaN differently
- * @since 3.4 Changed signature from max(double[]) to max(double...)
- */
- public static double max(final double... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- double max = array[0];
- for (int j = 1; j < array.length; j++) {
- if (Double.isNaN(array[j])) {
- return Double.NaN;
- }
- if (array[j] > max) {
- max = array[j];
- }
- }
-
- return max;
- }
-
- /**
- * Returns the maximum value in an array.
- *
- * @param array an array, must not be null or empty
- * @return the maximum value in the array
- * @throws IllegalArgumentException if array is null
- * @throws IllegalArgumentException if array is empty
- * @see IEEE754rUtils#max(float[]) IEEE754rUtils for a version of this method that handles NaN differently
- * @since 3.4 Changed signature from max(float[]) to max(float...)
- */
- public static float max(final float... array) {
- // Validates input
- validateArray(array);
-
- // Finds and returns max
- float max = array[0];
- for (int j = 1; j < array.length; j++) {
- if (Float.isNaN(array[j])) {
- return Float.NaN;
- }
- if (array[j] > max) {
- max = array[j];
- }
- }
-
- return max;
- }
-
- /**
- * Checks if the specified array is neither null nor empty.
- *
- * @param array the array to check
- * @throws IllegalArgumentException if {@code array} is either {@code null} or empty
- */
- private static void validateArray(final Object array) {
- Validate.isTrue(array != null, "The Array must not be null");
- Validate.isTrue(Array.getLength(array) != 0, "Array cannot be empty.");
- }
-
- // 3 param min
- //-----------------------------------------------------------------------
- /**
- * Gets the minimum of three long values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- */
- public static long min(long a, final long b, final long c) {
- if (b < a) {
- a = b;
- }
- if (c < a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the minimum of three int values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- */
- public static int min(int a, final int b, final int c) {
- if (b < a) {
- a = b;
- }
- if (c < a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the minimum of three short values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- */
- public static short min(short a, final short b, final short c) {
- if (b < a) {
- a = b;
- }
- if (c < a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the minimum of three byte values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- */
- public static byte min(byte a, final byte b, final byte c) {
- if (b < a) {
- a = b;
- }
- if (c < a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the minimum of three double values.
- *
- * If any value is NaN, NaN is
- * returned. Infinity is handled.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- * @see IEEE754rUtils#min(double, double, double) for a version of this method that handles NaN differently
- */
- public static double min(final double a, final double b, final double c) {
- return Math.min(Math.min(a, b), c);
- }
-
- /**
- * Gets the minimum of three float values.
- *
- * If any value is NaN, NaN is
- * returned. Infinity is handled.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
- * @see IEEE754rUtils#min(float, float, float) for a version of this method that handles NaN differently
- */
- public static float min(final float a, final float b, final float c) {
- return Math.min(Math.min(a, b), c);
- }
-
- // 3 param max
- //-----------------------------------------------------------------------
- /**
- * Gets the maximum of three long values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- */
- public static long max(long a, final long b, final long c) {
- if (b > a) {
- a = b;
- }
- if (c > a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the maximum of three int values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- */
- public static int max(int a, final int b, final int c) {
- if (b > a) {
- a = b;
- }
- if (c > a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the maximum of three short values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- */
- public static short max(short a, final short b, final short c) {
- if (b > a) {
- a = b;
- }
- if (c > a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the maximum of three byte values.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- */
- public static byte max(byte a, final byte b, final byte c) {
- if (b > a) {
- a = b;
- }
- if (c > a) {
- a = c;
- }
- return a;
- }
-
- /**
- * Gets the maximum of three double values.
- *
- * If any value is NaN, NaN is
- * returned. Infinity is handled.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- * @see IEEE754rUtils#max(double, double, double) for a version of this method that handles NaN differently
- */
- public static double max(final double a, final double b, final double c) {
- return Math.max(Math.max(a, b), c);
- }
-
- /**
- * Gets the maximum of three float values.
- *
- * If any value is NaN, NaN is
- * returned. Infinity is handled.
- *
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the largest of the values
- * @see IEEE754rUtils#max(float, float, float) for a version of this method that handles NaN differently
- */
- public static float max(final float a, final float b, final float c) {
- return Math.max(Math.max(a, b), c);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether the String contains only
- * digit characters.
- *
- * Null and empty String will return
- * false.
- *
- * @param str the String to check
- * @return true if str contains only Unicode numeric
- */
- public static boolean isDigits(final String str) {
- return StringUtils.isNumeric(str);
- }
-
- /**
- * Checks whether the String a valid Java number.
- *
- * Valid numbers include hexadecimal marked with the 0x or
- * 0X qualifier, octal numbers, scientific notation and
- * numbers marked with a type qualifier (e.g. 123L).
- *
- * Non-hexadecimal strings beginning with a leading zero are
- * treated as octal values. Thus the string 09 will return
- * false, since 9 is not a valid octal value.
- * However, numbers beginning with {@code 0.} are treated as decimal.
- *
- * null and empty/blank {@code String} will return
- * false.
- *
- * Note, {@link #createNumber(String)} should return a number for every
- * input resulting in true.
- *
- * @param str the String to check
- * @return true if the string is a correctly formatted number
- * @since 3.3 the code supports hex {@code 0Xhhh} an
- * octal {@code 0ddd} validation
- * @deprecated This feature will be removed in Lang 4.0,
- * use {@link NumberUtils#isCreatable(String)} instead
- */
- @Deprecated
- public static boolean isNumber(final String str) {
- return isCreatable(str);
- }
-
- /**
- * Checks whether the String a valid Java number.
- *
- * Valid numbers include hexadecimal marked with the 0x or
- * 0X qualifier, octal numbers, scientific notation and
- * numbers marked with a type qualifier (e.g. 123L).
- *
- * Non-hexadecimal strings beginning with a leading zero are
- * treated as octal values. Thus the string 09 will return
- * false, since 9 is not a valid octal value.
- * However, numbers beginning with {@code 0.} are treated as decimal.
- *
- * null and empty/blank {@code String} will return
- * false.
- *
- * Note, {@link #createNumber(String)} should return a number for every
- * input resulting in true.
- *
- * @param str the String to check
- * @return true if the string is a correctly formatted number
- * @since 3.5
- */
- public static boolean isCreatable(final String str) {
- if (StringUtils.isEmpty(str)) {
- return false;
- }
- final char[] chars = str.toCharArray();
- int sz = chars.length;
- boolean hasExp = false;
- boolean hasDecPoint = false;
- boolean allowSigns = false;
- boolean foundDigit = false;
- // deal with any possible sign up front
- final int start = chars[0] == '-' || chars[0] == '+' ? 1 : 0;
- if (sz > start + 1 && chars[start] == '0' && !StringUtils.contains(str, '.')) { // leading 0, skip if is a decimal number
- if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X
- int i = start + 2;
- if (i == sz) {
- return false; // str == "0x"
- }
- // checking hex (it can't be anything else)
- for (; i < chars.length; i++) {
- if ((chars[i] < '0' || chars[i] > '9')
- && (chars[i] < 'a' || chars[i] > 'f')
- && (chars[i] < 'A' || chars[i] > 'F')) {
- return false;
- }
- }
- return true;
- } else if (Character.isDigit(chars[start + 1])) {
- // leading 0, but not hex, must be octal
- int i = start + 1;
- for (; i < chars.length; i++) {
- if (chars[i] < '0' || chars[i] > '7') {
- return false;
- }
- }
- return true;
- }
- }
- sz--; // don't want to loop to the last char, check it afterwords
- // for type qualifiers
- int i = start;
- // loop to the next to last char or to the last char if we need another digit to
- // make a valid number (e.g. chars[0..5] = "1234E")
- while (i < sz || i < sz + 1 && allowSigns && !foundDigit) {
- if (chars[i] >= '0' && chars[i] <= '9') {
- foundDigit = true;
- allowSigns = false;
-
- } else if (chars[i] == '.') {
- if (hasDecPoint || hasExp) {
- // two decimal points or dec in exponent
- return false;
- }
- hasDecPoint = true;
- } else if (chars[i] == 'e' || chars[i] == 'E') {
- // we've already taken care of hex.
- if (hasExp) {
- // two E's
- return false;
- }
- if (!foundDigit) {
- return false;
- }
- hasExp = true;
- allowSigns = true;
- } else if (chars[i] == '+' || chars[i] == '-') {
- if (!allowSigns) {
- return false;
- }
- allowSigns = false;
- foundDigit = false; // we need a digit after the E
- } else {
- return false;
- }
- i++;
- }
- if (i < chars.length) {
- if (chars[i] >= '0' && chars[i] <= '9') {
- // no type qualifier, OK
- return true;
- }
- if (chars[i] == 'e' || chars[i] == 'E') {
- // can't have an E at the last byte
- return false;
- }
- if (chars[i] == '.') {
- if (hasDecPoint || hasExp) {
- // two decimal points or dec in exponent
- return false;
- }
- // single trailing decimal point after non-exponent is ok
- return foundDigit;
- }
- if (!allowSigns
- && (chars[i] == 'd'
- || chars[i] == 'D'
- || chars[i] == 'f'
- || chars[i] == 'F')) {
- return foundDigit;
- }
- if (chars[i] == 'l'
- || chars[i] == 'L') {
- // not allowing L with an exponent or decimal point
- return foundDigit && !hasExp && !hasDecPoint;
- }
- // last character is illegal
- return false;
- }
- // allowSigns is true iff the val ends in 'E'
- // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
- return !allowSigns && foundDigit;
- }
-
- /**
- * Checks whether the given String is a parsable number.
- *
- * Parsable numbers include those Strings understood by {@link Integer#parseInt(String)},
- * {@link Long#parseLong(String)}, {@link Float#parseFloat(String)} or
- * {@link Double#parseDouble(String)}. This method can be used instead of catching {@link java.text.ParseException}
- * when calling one of those methods.
- *
- * Hexadecimal and scientific notations are not considered parsable.
- * See {@link #isCreatable(String)} on those cases.
- *
- * {@code Null} and empty String will return false.
- *
- * @param str the String to check.
- * @return {@code true} if the string is a parsable number.
- * @since 3.4
- */
- public static boolean isParsable(final String str) {
- if (StringUtils.isEmpty(str)) {
- return false;
- }
- if (str.charAt(str.length() - 1) == '.') {
- return false;
- }
- if (str.charAt(0) == '-') {
- if (str.length() == 1) {
- return false;
- }
- return withDecimalsParsing(str, 1);
- }
- return withDecimalsParsing(str, 0);
- }
-
- private static boolean withDecimalsParsing(final String str, final int beginIdx) {
- int decimalPoints = 0;
- for (int i = beginIdx; i < str.length(); i++) {
- final boolean isDecimalPoint = str.charAt(i) == '.';
- if (isDecimalPoint) {
- decimalPoints++;
- }
- if (decimalPoints > 1) {
- return false;
- }
- if (!isDecimalPoint && !Character.isDigit(str.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Compares two {@code int} values numerically. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code int} to compare
- * @param y the second {@code int} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code x < y}; and
- * a value greater than {@code 0} if {@code x > y}
- * @since 3.4
- */
- public static int compare(final int x, final int y) {
- if (x == y) {
- return 0;
- }
- return x < y ? -1 : 1;
- }
-
- /**
- * Compares to {@code long} values numerically. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code long} to compare
- * @param y the second {@code long} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code x < y}; and
- * a value greater than {@code 0} if {@code x > y}
- * @since 3.4
- */
- public static int compare(final long x, final long y) {
- if (x == y) {
- return 0;
- }
- return x < y ? -1 : 1;
- }
-
- /**
- * Compares to {@code short} values numerically. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code short} to compare
- * @param y the second {@code short} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code x < y}; and
- * a value greater than {@code 0} if {@code x > y}
- * @since 3.4
- */
- public static int compare(final short x, final short y) {
- if (x == y) {
- return 0;
- }
- return x < y ? -1 : 1;
- }
-
- /**
- * Compares two {@code byte} values numerically. This is the same functionality as provided in Java 7.
- *
- * @param x the first {@code byte} to compare
- * @param y the second {@code byte} to compare
- * @return the value {@code 0} if {@code x == y};
- * a value less than {@code 0} if {@code x < y}; and
- * a value greater than {@code 0} if {@code x > y}
- * @since 3.4
- */
- public static int compare(final byte x, final byte y) {
- return x - y;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ObjectUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ObjectUtils.java
deleted file mode 100644
index c1cf5772..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ObjectUtils.java
+++ /dev/null
@@ -1,1043 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeSet;
-
-/**
- * Operations on {@code Object}.
- *
- * This class tries to handle {@code null} input gracefully.
- * An exception will generally not be thrown for a {@code null} input.
- * Each method documents its behaviour in more detail.
- *
- * #ThreadSafe#
- * @since 1.0
- */
-//@Immutable
-@SuppressWarnings("deprecation") // deprecated class StrBuilder is imported
-// because it is part of the signature of deprecated methods
-public class ObjectUtils {
-
- private static final char AT_SIGN = '@';
-
- /**
- * Singleton used as a {@code null} placeholder where
- * {@code null} has another meaning.
- *
- * For example, in a {@code HashMap} the
- * {@link HashMap#get(Object)} method returns
- * {@code null} if the {@code Map} contains {@code null} or if there
- * is no matching key. The {@code Null} placeholder can be used to
- * distinguish between these two cases.
- *
- * Another example is {@code Hashtable}, where {@code null}
- * cannot be stored.
- *
- * This instance is Serializable.
- */
- public static final Null NULL = new Null();
-
- /**
- * {@code ObjectUtils} instances should NOT be constructed in
- * standard programming. Instead, the static methods on the class should
- * be used, such as {@code ObjectUtils.defaultIfNull("a","b");}.
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
- */
- public ObjectUtils() {
- super();
- }
-
- // Defaulting
- //-----------------------------------------------------------------------
- /**
- * Returns a default value if the object passed is {@code null}.
- *
- *
- * ObjectUtils.defaultIfNull(null, null) = null
- * ObjectUtils.defaultIfNull(null, "") = ""
- * ObjectUtils.defaultIfNull(null, "zz") = "zz"
- * ObjectUtils.defaultIfNull("abc", *) = "abc"
- * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
- *
- *
- * @param the type of the object
- * @param object the {@code Object} to test, may be {@code null}
- * @param defaultValue the default value to return, may be {@code null}
- * @return {@code object} if it is not {@code null}, defaultValue otherwise
- */
- public static T defaultIfNull(final T object, final T defaultValue) {
- return object != null ? object : defaultValue;
- }
-
- /**
- * Returns the first value in the array which is not {@code null}.
- * If all the values are {@code null} or the array is {@code null}
- * or empty then {@code null} is returned.
- *
- *
- * ObjectUtils.firstNonNull(null, null) = null
- * ObjectUtils.firstNonNull(null, "") = ""
- * ObjectUtils.firstNonNull(null, null, "") = ""
- * ObjectUtils.firstNonNull(null, "zz") = "zz"
- * ObjectUtils.firstNonNull("abc", *) = "abc"
- * ObjectUtils.firstNonNull(null, "xyz", *) = "xyz"
- * ObjectUtils.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE
- * ObjectUtils.firstNonNull() = null
- *
- *
- * @param the component type of the array
- * @param values the values to test, may be {@code null} or empty
- * @return the first value from {@code values} which is not {@code null},
- * or {@code null} if there are no non-null values
- * @since 3.0
- */
- @SafeVarargs
- public static T firstNonNull(final T... values) {
- if (values != null) {
- for (final T val : values) {
- if (val != null) {
- return val;
- }
- }
- }
- return null;
- }
-
- /**
- * Checks if any value in the given array is not {@code null}.
- *
- *
- * If all the values are {@code null} or the array is {@code null}
- * or empty then {@code false} is returned. Otherwise {@code true} is returned.
- *
- *
- *
- * ObjectUtils.anyNotNull(*) = true
- * ObjectUtils.anyNotNull(*, null) = true
- * ObjectUtils.anyNotNull(null, *) = true
- * ObjectUtils.anyNotNull(null, null, *, *) = true
- * ObjectUtils.anyNotNull(null) = false
- * ObjectUtils.anyNotNull(null, null) = false
- *
- *
- * @param values the values to test, may be {@code null} or empty
- * @return {@code true} if there is at least one non-null value in the array,
- * {@code false} if all values in the array are {@code null}s.
- * If the array is {@code null} or empty {@code false} is also returned.
- * @since 3.5
- */
- public static boolean anyNotNull(final Object... values) {
- return firstNonNull(values) != null;
- }
-
- /**
- * Checks if all values in the array are not {@code nulls}.
- *
- *
- * If any value is {@code null} or the array is {@code null} then
- * {@code false} is returned. If all elements in array are not
- * {@code null} or the array is empty (contains no elements) {@code true}
- * is returned.
- *
- *
- *
- * ObjectUtils.allNotNull(*) = true
- * ObjectUtils.allNotNull(*, *) = true
- * ObjectUtils.allNotNull(null) = false
- * ObjectUtils.allNotNull(null, null) = false
- * ObjectUtils.allNotNull(null, *) = false
- * ObjectUtils.allNotNull(*, null) = false
- * ObjectUtils.allNotNull(*, *, null, *) = false
- *
- *
- * @param values the values to test, may be {@code null} or empty
- * @return {@code false} if there is at least one {@code null} value in the array or the array is {@code null},
- * {@code true} if all values in the array are not {@code null}s or array contains no elements.
- * @since 3.5
- */
- public static boolean allNotNull(final Object... values) {
- if (values == null) {
- return false;
- }
-
- for (final Object val : values) {
- if (val == null) {
- return false;
- }
- }
-
- return true;
- }
-
- // Null-safe equals/hashCode
- //-----------------------------------------------------------------------
- /**
- * Compares two objects for equality, where either one or both
- * objects may be {@code null}.
- *
- *
- * ObjectUtils.equals(null, null) = true
- * ObjectUtils.equals(null, "") = false
- * ObjectUtils.equals("", null) = false
- * ObjectUtils.equals("", "") = true
- * ObjectUtils.equals(Boolean.TRUE, null) = false
- * ObjectUtils.equals(Boolean.TRUE, "true") = false
- * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE) = true
- * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
- *
- *
- * @param object1 the first object, may be {@code null}
- * @param object2 the second object, may be {@code null}
- * @return {@code true} if the values of both objects are the same
- * @deprecated this method has been replaced by {@code java.util.Objects.equals(Object, Object)} in Java 7 and will
- * be removed from future releases.
- */
- @Deprecated
- public static boolean equals(final Object object1, final Object object2) {
- if (object1 == object2) {
- return true;
- }
- if (object1 == null || object2 == null) {
- return false;
- }
- return object1.equals(object2);
- }
-
- /**
- * Compares two objects for inequality, where either one or both
- * objects may be {@code null}.
- *
- *
- * ObjectUtils.notEqual(null, null) = false
- * ObjectUtils.notEqual(null, "") = true
- * ObjectUtils.notEqual("", null) = true
- * ObjectUtils.notEqual("", "") = false
- * ObjectUtils.notEqual(Boolean.TRUE, null) = true
- * ObjectUtils.notEqual(Boolean.TRUE, "true") = true
- * ObjectUtils.notEqual(Boolean.TRUE, Boolean.TRUE) = false
- * ObjectUtils.notEqual(Boolean.TRUE, Boolean.FALSE) = true
- *
- *
- * @param object1 the first object, may be {@code null}
- * @param object2 the second object, may be {@code null}
- * @return {@code false} if the values of both objects are the same
- */
- public static boolean notEqual(final Object object1, final Object object2) {
- return !equals(object1, object2);
- }
-
- /**
- * Gets the hash code of an object returning zero when the
- * object is {@code null}.
- *
- *
- * ObjectUtils.hashCode(null) = 0
- * ObjectUtils.hashCode(obj) = obj.hashCode()
- *
- *
- * @param obj the object to obtain the hash code of, may be {@code null}
- * @return the hash code of the object, or zero if null
- * @since 2.1
- * @deprecated this method has been replaced by {@code java.util.Objects.hashCode(Object)} in Java 7 and will be
- * removed in future releases
- */
- @Deprecated
- public static int hashCode(final Object obj) {
- // hashCode(Object) retained for performance, as hash code is often critical
- return obj == null ? 0 : obj.hashCode();
- }
-
- /**
- * Gets the hash code for multiple objects.
- *
- * This allows a hash code to be rapidly calculated for a number of objects.
- * The hash code for a single object is the not same as {@link #hashCode(Object)}.
- * The hash code for multiple objects is the same as that calculated by an
- * {@code ArrayList} containing the specified objects.
- *
- *
- * ObjectUtils.hashCodeMulti() = 1
- * ObjectUtils.hashCodeMulti((Object[]) null) = 1
- * ObjectUtils.hashCodeMulti(a) = 31 + a.hashCode()
- * ObjectUtils.hashCodeMulti(a,b) = (31 + a.hashCode()) * 31 + b.hashCode()
- * ObjectUtils.hashCodeMulti(a,b,c) = ((31 + a.hashCode()) * 31 + b.hashCode()) * 31 + c.hashCode()
- *
- *
- * @param objects the objects to obtain the hash code of, may be {@code null}
- * @return the hash code of the objects, or zero if null
- * @since 3.0
- * @deprecated this method has been replaced by {@code java.util.Objects.hash(Object...)} in Java 7 and will be
- * removed in future releases.
- */
- @Deprecated
- public static int hashCodeMulti(final Object... objects) {
- int hash = 1;
- if (objects != null) {
- for (final Object object : objects) {
- final int tmpHash = hashCode(object);
- hash = hash * 31 + tmpHash;
- }
- }
- return hash;
- }
-
- // Identity ToString
- //-----------------------------------------------------------------------
- /**
- * Gets the toString that would be produced by {@code Object}
- * if a class did not override toString itself. {@code null}
- * will return {@code null}.
- *
- *
- * ObjectUtils.identityToString(null) = null
- * ObjectUtils.identityToString("") = "java.lang.String@1e23"
- * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
- *
- *
- * @param object the object to create a toString for, may be
- * {@code null}
- * @return the default toString text, or {@code null} if
- * {@code null} passed in
- */
- public static String identityToString(final Object object) {
- if (object == null) {
- return null;
- }
- final String name = object.getClass().getName();
- final String hexString = Integer.toHexString(System.identityHashCode(object));
- final StringBuilder builder = new StringBuilder(name.length() + 1 + hexString.length());
- // @formatter:off
- builder.append(name)
- .append(AT_SIGN)
- .append(hexString);
- // @formatter:off
- return builder.toString();
- }
-
- /**
- * Appends the toString that would be produced by {@code Object}
- * if a class did not override toString itself. {@code null}
- * will throw a NullPointerException for either of the two parameters.
- *
- *
- * ObjectUtils.identityToString(appendable, "") = appendable.append("java.lang.String@1e23"
- * ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa"
- * ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa")
- *
- *
- * @param appendable the appendable to append to
- * @param object the object to create a toString for
- * @throws IOException if an I/O error occurs
- * @since 3.2
- */
- public static void identityToString(final Appendable appendable, final Object object) throws IOException {
- Validate.notNull(object, "Cannot get the toString of a null object");
- appendable.append(object.getClass().getName())
- .append(AT_SIGN)
- .append(Integer.toHexString(System.identityHashCode(object)));
- }
-
- /**
- * Appends the toString that would be produced by {@code Object}
- * if a class did not override toString itself. {@code null}
- * will throw a NullPointerException for either of the two parameters.
- *
- *
- * ObjectUtils.identityToString(builder, "") = builder.append("java.lang.String@1e23"
- * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa"
- * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa")
- *
- *
- * @param builder the builder to append to
- * @param object the object to create a toString for
- * @since 3.2
- * @deprecated as of 3.6, because StrBuilder was moved to commons-text,
- * use one of the other {@code identityToString} methods instead
- */
- @Deprecated
- public static void identityToString(final StrBuilder builder, final Object object) {
- Validate.notNull(object, "Cannot get the toString of a null object");
- final String name = object.getClass().getName();
- final String hexString = Integer.toHexString(System.identityHashCode(object));
- builder.ensureCapacity(builder.length() + name.length() + 1 + hexString.length());
- builder.append(name)
- .append(AT_SIGN)
- .append(hexString);
- }
-
- /**
- * Appends the toString that would be produced by {@code Object}
- * if a class did not override toString itself. {@code null}
- * will throw a NullPointerException for either of the two parameters.
- *
- *
- * ObjectUtils.identityToString(buf, "") = buf.append("java.lang.String@1e23"
- * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa"
- * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
- *
- *
- * @param buffer the buffer to append to
- * @param object the object to create a toString for
- * @since 2.4
- */
- public static void identityToString(final StringBuffer buffer, final Object object) {
- Validate.notNull(object, "Cannot get the toString of a null object");
- final String name = object.getClass().getName();
- final String hexString = Integer.toHexString(System.identityHashCode(object));
- buffer.ensureCapacity(buffer.length() + name.length() + 1 + hexString.length());
- buffer.append(name)
- .append(AT_SIGN)
- .append(hexString);
- }
-
- /**
- * Appends the toString that would be produced by {@code Object}
- * if a class did not override toString itself. {@code null}
- * will throw a NullPointerException for either of the two parameters.
- *
- *
- * ObjectUtils.identityToString(builder, "") = builder.append("java.lang.String@1e23"
- * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa"
- * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa")
- *
- *
- * @param builder the builder to append to
- * @param object the object to create a toString for
- * @since 3.2
- */
- public static void identityToString(final StringBuilder builder, final Object object) {
- Validate.notNull(object, "Cannot get the toString of a null object");
- final String name = object.getClass().getName();
- final String hexString = Integer.toHexString(System.identityHashCode(object));
- builder.ensureCapacity(builder.length() + name.length() + 1 + hexString.length());
- builder.append(name)
- .append(AT_SIGN)
- .append(hexString);
- }
-
- // ToString
- //-----------------------------------------------------------------------
- /**
- * Gets the {@code toString} of an {@code Object} returning
- * an empty string ("") if {@code null} input.
- *
- *
- * ObjectUtils.toString(null) = ""
- * ObjectUtils.toString("") = ""
- * ObjectUtils.toString("bat") = "bat"
- * ObjectUtils.toString(Boolean.TRUE) = "true"
- *
- *
- * @see StringUtils#defaultString(String)
- * @see String#valueOf(Object)
- * @param obj the Object to {@code toString}, may be null
- * @return the passed in Object's toString, or {@code ""} if {@code null} input
- * @since 2.0
- * @deprecated this method has been replaced by {@code java.util.Objects.toString(Object)} in Java 7 and will be
- * removed in future releases. Note however that said method will return "null" for null references, while this
- * method returns an empty String. To preserve behavior use {@code java.util.Objects.toString(myObject, "")}
- */
- @Deprecated
- public static String toString(final Object obj) {
- return obj == null ? StringUtils.EMPTY : obj.toString();
- }
-
- /**
- * Gets the {@code toString} of an {@code Object} returning
- * a specified text if {@code null} input.
- *
- *
- * ObjectUtils.toString(null, null) = null
- * ObjectUtils.toString(null, "null") = "null"
- * ObjectUtils.toString("", "null") = ""
- * ObjectUtils.toString("bat", "null") = "bat"
- * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
- *
- *
- * @see StringUtils#defaultString(String,String)
- * @see String#valueOf(Object)
- * @param obj the Object to {@code toString}, may be null
- * @param nullStr the String to return if {@code null} input, may be null
- * @return the passed in Object's toString, or {@code nullStr} if {@code null} input
- * @since 2.0
- * @deprecated this method has been replaced by {@code java.util.Objects.toString(Object, String)} in Java 7 and
- * will be removed in future releases.
- */
- @Deprecated
- public static String toString(final Object obj, final String nullStr) {
- return obj == null ? nullStr : obj.toString();
- }
-
- // Comparable
- //-----------------------------------------------------------------------
- /**
- * Null safe comparison of Comparables.
- *
- * @param type of the values processed by this method
- * @param values the set of comparable values, may be null
- * @return
- *
- * If any objects are non-null and unequal, the lesser object.
- * If all objects are non-null and equal, the first.
- * If any of the comparables are null, the lesser of the non-null objects.
- * If all the comparables are null, null is returned.
- *
- */
- @SafeVarargs
- public static > T min(final T... values) {
- T result = null;
- if (values != null) {
- for (final T value : values) {
- if (compare(value, result, true) < 0) {
- result = value;
- }
- }
- }
- return result;
- }
-
- /**
- * Null safe comparison of Comparables.
- *
- * @param type of the values processed by this method
- * @param values the set of comparable values, may be null
- * @return
- *
- * If any objects are non-null and unequal, the greater object.
- * If all objects are non-null and equal, the first.
- * If any of the comparables are null, the greater of the non-null objects.
- * If all the comparables are null, null is returned.
- *
- */
- @SafeVarargs
- public static > T max(final T... values) {
- T result = null;
- if (values != null) {
- for (final T value : values) {
- if (compare(value, result, false) > 0) {
- result = value;
- }
- }
- }
- return result;
- }
-
- /**
- * Null safe comparison of Comparables.
- * {@code null} is assumed to be less than a non-{@code null} value.
- *
- * @param type of the values processed by this method
- * @param c1 the first comparable, may be null
- * @param c2 the second comparable, may be null
- * @return a negative value if c1 < c2, zero if c1 = c2
- * and a positive value if c1 > c2
- */
- public static > int compare(final T c1, final T c2) {
- return compare(c1, c2, false);
- }
-
- /**
- * Null safe comparison of Comparables.
- *
- * @param type of the values processed by this method
- * @param c1 the first comparable, may be null
- * @param c2 the second comparable, may be null
- * @param nullGreater if true {@code null} is considered greater
- * than a non-{@code null} value or if false {@code null} is
- * considered less than a Non-{@code null} value
- * @return a negative value if c1 < c2, zero if c1 = c2
- * and a positive value if c1 > c2
- * @see Comparator#compare(Object, Object)
- */
- public static > int compare(final T c1, final T c2, final boolean nullGreater) {
- if (c1 == c2) {
- return 0;
- } else if (c1 == null) {
- return nullGreater ? 1 : -1;
- } else if (c2 == null) {
- return nullGreater ? -1 : 1;
- }
- return c1.compareTo(c2);
- }
-
- /**
- * Find the "best guess" middle value among comparables. If there is an even
- * number of total values, the lower of the two middle values will be returned.
- * @param type of values processed by this method
- * @param items to compare
- * @return T at middle position
- * @throws NullPointerException if items is {@code null}
- * @throws IllegalArgumentException if items is empty or contains {@code null} values
- * @since 3.0.1
- */
- @SafeVarargs
- public static > T median(final T... items) {
- Validate.notEmpty(items);
- Validate.noNullElements(items);
- final TreeSet sort = new TreeSet<>();
- Collections.addAll(sort, items);
- @SuppressWarnings("unchecked") //we know all items added were T instances
- final T result = (T) sort.toArray()[(sort.size() - 1) / 2];
- return result;
- }
-
- /**
- * Find the "best guess" middle value among comparables. If there is an even
- * number of total values, the lower of the two middle values will be returned.
- * @param type of values processed by this method
- * @param comparator to use for comparisons
- * @param items to compare
- * @return T at middle position
- * @throws NullPointerException if items or comparator is {@code null}
- * @throws IllegalArgumentException if items is empty or contains {@code null} values
- * @since 3.0.1
- */
- @SafeVarargs
- public static T median(final Comparator comparator, final T... items) {
- Validate.notEmpty(items, "null/empty items");
- Validate.noNullElements(items);
- Validate.notNull(comparator, "null comparator");
- final TreeSet sort = new TreeSet<>(comparator);
- Collections.addAll(sort, items);
- @SuppressWarnings("unchecked") //we know all items added were T instances
- final
- T result = (T) sort.toArray()[(sort.size() - 1) / 2];
- return result;
- }
-
- // Mode
- //-----------------------------------------------------------------------
- /**
- * Find the most frequently occurring item.
- *
- * @param type of values processed by this method
- * @param items to check
- * @return most populous T, {@code null} if non-unique or no items supplied
- * @since 3.0.1
- */
- @SafeVarargs
- public static T mode(final T... items) {
- if (ArrayUtils.isNotEmpty(items)) {
- final HashMap occurrences = new HashMap<>(items.length);
- for (final T t : items) {
- final MutableInt count = occurrences.get(t);
- if (count == null) {
- occurrences.put(t, new MutableInt(1));
- } else {
- count.increment();
- }
- }
- T result = null;
- int max = 0;
- for (final Map.Entry e : occurrences.entrySet()) {
- final int cmp = e.getValue().intValue();
- if (cmp == max) {
- result = null;
- } else if (cmp > max) {
- max = cmp;
- result = e.getKey();
- }
- }
- return result;
- }
- return null;
- }
-
- // cloning
- //-----------------------------------------------------------------------
- /**
- * Clone an object.
- *
- * @param the type of the object
- * @param obj the object to clone, null returns null
- * @return the clone if the object implements {@link Cloneable} otherwise {@code null}
- * @since 3.0
- */
-// public static T clone(final T obj) {
-// if (obj instanceof Cloneable) {
-// final Object result;
-// if (obj.getClass().isArray()) {
-// final Class> componentType = obj.getClass().getComponentType();
-// if (componentType.isPrimitive()) {
-// int length = Array.getLength(obj);
-// result = Array.newInstance(componentType, length);
-// while (length-- > 0) {
-// Array.set(result, length, Array.get(obj, length));
-// }
-// } else {
-// result = ((Object[]) obj).clone();
-// }
-// } else {
-// try {
-// final Method clone = obj.getClass().getMethod("clone");
-// result = clone.invoke(obj);
-// } catch (final NoSuchMethodException e) {
-// throw new CloneFailedException("Cloneable type "
-// + obj.getClass().getName()
-// + " has no clone method", e);
-// } catch (final IllegalAccessException e) {
-// throw new CloneFailedException("Cannot clone Cloneable type "
-// + obj.getClass().getName(), e);
-// } catch (final InvocationTargetException e) {
-// throw new CloneFailedException("Exception cloning Cloneable type "
-// + obj.getClass().getName(), e.getCause());
-// }
-// }
-// @SuppressWarnings("unchecked") // OK because input is of type T
-// final T checked = (T) result;
-// return checked;
-// }
-//
-// return null;
-// }
-
- /**
- * Clone an object if possible.
- *
- * instance as the return value instead of {@code null} if the instance
- * is not cloneable. This is more convenient if the caller uses different
- * implementations (e.g. of a service) and some of the implementations do not allow concurrent
- * processing or have state. In such cases the implementation can simply provide a proper
- * clone implementation and the caller's code does not have to change.
- *
- * @param the type of the object
- * @param obj the object to clone, null returns null
- * @return the clone if the object implements {@link Cloneable} otherwise the object itself
- * @since 3.0
- */
-// public static T cloneIfPossible(final T obj) {
-// final T clone = clone(obj);
-// return clone == null ? obj : clone;
-// }
-
- // Null
- //-----------------------------------------------------------------------
- /**
- * Class used as a null placeholder where {@code null}
- * has another meaning.
- *
- * For example, in a {@code HashMap} the
- * {@link HashMap#get(Object)} method returns
- * {@code null} if the {@code Map} contains {@code null} or if there is
- * no matching key. The {@code Null} placeholder can be used to distinguish
- * between these two cases.
- *
- * Another example is {@code Hashtable}, where {@code null}
- * cannot be stored.
- */
- public static class Null implements Serializable {
- /**
- * Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
- *
- * @see Serializable
- */
- private static final long serialVersionUID = 7092611880189329093L;
-
- /**
- * Restricted constructor - singleton.
- */
- Null() {
- super();
- }
-
- /**
- * Ensure singleton.
- *
- * @return the singleton value
- */
- private Object readResolve() {
- return NULL;
- }
- }
-
-
- // Constants (LANG-816):
- /*
- These methods ensure constants are not inlined by javac.
- For example, typically a developer might declare a constant like so:
-
- public final static int MAGIC_NUMBER = 5;
-
- Should a different jar file refer to this, and the MAGIC_NUMBER
- is changed a later date (e.g., MAGIC_NUMBER = 6), the different jar
- file will need to recompile itself. This is because javac
- typically inlines the primitive or String constant directly into
- the bytecode, and removes the reference to the MAGIC_NUMBER field.
-
- To help the other jar (so that it does not need to recompile
- when constants are changed) the original developer can declare
- their constant using one of the CONST() utility methods, instead:
-
- public final static int MAGIC_NUMBER = CONST(5);
- */
-
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static boolean MAGIC_FLAG = ObjectUtils.CONST(true);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the boolean value to return
- * @return the boolean v, unchanged
- * @since 3.2
- */
- public static boolean CONST(final boolean v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static byte MAGIC_BYTE = ObjectUtils.CONST((byte) 127);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the byte value to return
- * @return the byte v, unchanged
- * @since 3.2
- */
- public static byte CONST(final byte v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static byte MAGIC_BYTE = ObjectUtils.CONST_BYTE(127);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the byte literal (as an int) value to return
- * @throws IllegalArgumentException if the value passed to v
- * is larger than a byte, that is, smaller than -128 or
- * larger than 127.
- * @return the byte v, unchanged
- * @since 3.2
- */
- public static byte CONST_BYTE(final int v) {
- if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
- throw new IllegalArgumentException("Supplied value must be a valid byte literal between -128 and 127: [" + v + "]");
- }
- return (byte) v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static char MAGIC_CHAR = ObjectUtils.CONST('a');
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the char value to return
- * @return the char v, unchanged
- * @since 3.2
- */
- public static char CONST(final char v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static short MAGIC_SHORT = ObjectUtils.CONST((short) 123);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the short value to return
- * @return the short v, unchanged
- * @since 3.2
- */
- public static short CONST(final short v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static short MAGIC_SHORT = ObjectUtils.CONST_SHORT(127);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the short literal (as an int) value to return
- * @throws IllegalArgumentException if the value passed to v
- * is larger than a short, that is, smaller than -32768 or
- * larger than 32767.
- * @return the byte v, unchanged
- * @since 3.2
- */
- public static short CONST_SHORT(final int v) {
- if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
- throw new IllegalArgumentException("Supplied value must be a valid byte literal between -32768 and 32767: [" + v + "]");
- }
- return (short) v;
- }
-
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static int MAGIC_INT = ObjectUtils.CONST(123);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the int value to return
- * @return the int v, unchanged
- * @since 3.2
- */
- public static int CONST(final int v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static long MAGIC_LONG = ObjectUtils.CONST(123L);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the long value to return
- * @return the long v, unchanged
- * @since 3.2
- */
- public static long CONST(final long v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static float MAGIC_FLOAT = ObjectUtils.CONST(1.0f);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the float value to return
- * @return the float v, unchanged
- * @since 3.2
- */
- public static float CONST(final float v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static double MAGIC_DOUBLE = ObjectUtils.CONST(1.0);
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param v the double value to return
- * @return the double v, unchanged
- * @since 3.2
- */
- public static double CONST(final double v) {
- return v;
- }
-
- /**
- * This method returns the provided value unchanged.
- * This can prevent javac from inlining a constant
- * field, e.g.,
- *
- *
- * public final static String MAGIC_STRING = ObjectUtils.CONST("abc");
- *
- *
- * This way any jars that refer to this field do not
- * have to recompile themselves if the field's value
- * changes at some future date.
- *
- * @param the Object type
- * @param v the genericized Object value to return (typically a String).
- * @return the genericized Object v, unchanged (typically a String).
- * @since 3.2
- */
- public static T CONST(final T v) {
- return v;
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Range.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Range.java
deleted file mode 100644
index e7f8ff29..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Range.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * An immutable range of objects from a minimum to maximum point inclusive.
- *
- * The objects need to either be implementations of {@code Comparable}
- * or you need to supply a {@code Comparator}.
- *
- * #ThreadSafe# if the objects and comparator are thread-safe
- *
- * @since 3.0
- */
-public final class Range implements Serializable {
-
- /**
- * Serialization version.
- * @see Serializable
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * The ordering scheme used in this range.
- */
- private final Comparator comparator;
- /**
- * The minimum value in this range (inclusive).
- */
- private final T minimum;
- /**
- * The maximum value in this range (inclusive).
- */
- private final T maximum;
- /**
- * Cached output hashCode (class is immutable).
- */
- private transient int hashCode;
- /**
- * Cached output toString (class is immutable).
- */
- private transient String toString;
-
- /**
- * Obtains a range using the specified element as both the minimum
- * and maximum in this range.
- *
- * The range uses the natural ordering of the elements to determine where
- * values lie in the range.
- *
- * @param the type of the elements in this range
- * @param element the value to use for this range, not null
- * @return the range object, not null
- * @throws IllegalArgumentException if the element is null
- * @throws ClassCastException if the element is not {@code Comparable}
- */
- public static > Range is(final T element) {
- return between(element, element, null);
- }
-
- /**
- * Obtains a range using the specified element as both the minimum
- * and maximum in this range.
- *
- * The range uses the specified {@code Comparator} to determine where
- * values lie in the range.
- *
- * @param the type of the elements in this range
- * @param element the value to use for this range, must not be {@code null}
- * @param comparator the comparator to be used, null for natural ordering
- * @return the range object, not null
- * @throws IllegalArgumentException if the element is null
- * @throws ClassCastException if using natural ordering and the elements are not {@code Comparable}
- */
- public static Range is(final T element, final Comparator comparator) {
- return between(element, element, comparator);
- }
-
- /**
- * Obtains a range with the specified minimum and maximum values (both inclusive).
- *
- * The range uses the natural ordering of the elements to determine where
- * values lie in the range.
- *
- * The arguments may be passed in the order (min,max) or (max,min).
- * The getMinimum and getMaximum methods will return the correct values.
- *
- * @param the type of the elements in this range
- * @param fromInclusive the first value that defines the edge of the range, inclusive
- * @param toInclusive the second value that defines the edge of the range, inclusive
- * @return the range object, not null
- * @throws IllegalArgumentException if either element is null
- * @throws ClassCastException if the elements are not {@code Comparable}
- */
- public static > Range between(final T fromInclusive, final T toInclusive) {
- return between(fromInclusive, toInclusive, null);
- }
-
- /**
- * Obtains a range with the specified minimum and maximum values (both inclusive).
- *
- * The range uses the specified {@code Comparator} to determine where
- * values lie in the range.
- *
- * The arguments may be passed in the order (min,max) or (max,min).
- * The getMinimum and getMaximum methods will return the correct values.
- *
- * @param the type of the elements in this range
- * @param fromInclusive the first value that defines the edge of the range, inclusive
- * @param toInclusive the second value that defines the edge of the range, inclusive
- * @param comparator the comparator to be used, null for natural ordering
- * @return the range object, not null
- * @throws IllegalArgumentException if either element is null
- * @throws ClassCastException if using natural ordering and the elements are not {@code Comparable}
- */
- public static Range between(final T fromInclusive, final T toInclusive, final Comparator comparator) {
- return new Range<>(fromInclusive, toInclusive, comparator);
- }
-
- /**
- * Creates an instance.
- *
- * @param element1 the first element, not null
- * @param element2 the second element, not null
- * @param comp the comparator to be used, null for natural ordering
- */
- @SuppressWarnings("unchecked")
- private Range(final T element1, final T element2, final Comparator comp) {
- if (element1 == null || element2 == null) {
- throw new IllegalArgumentException("Elements in a range must not be null: element1=" +
- element1 + ", element2=" + element2);
- }
- if (comp == null) {
- this.comparator = ComparableComparator.INSTANCE;
- } else {
- this.comparator = comp;
- }
- if (this.comparator.compare(element1, element2) < 1) {
- this.minimum = element1;
- this.maximum = element2;
- } else {
- this.minimum = element2;
- this.maximum = element1;
- }
- }
-
- // Accessors
- //--------------------------------------------------------------------
-
- /**
- * Gets the minimum value in this range.
- *
- * @return the minimum value in this range, not null
- */
- public T getMinimum() {
- return minimum;
- }
-
- /**
- * Gets the maximum value in this range.
- *
- * @return the maximum value in this range, not null
- */
- public T getMaximum() {
- return maximum;
- }
-
- /**
- * Gets the comparator being used to determine if objects are within the range.
- *
- * Natural ordering uses an internal comparator implementation, thus this
- * method never returns null. See {@link #isNaturalOrdering()}.
- *
- * @return the comparator being used, not null
- */
- public Comparator getComparator() {
- return comparator;
- }
-
- /**
- * Whether or not the Range is using the natural ordering of the elements.
- *
- * Natural ordering uses an internal comparator implementation, thus this
- * method is the only way to check if a null comparator was specified.
- *
- * @return true if using natural ordering
- */
- public boolean isNaturalOrdering() {
- return comparator == ComparableComparator.INSTANCE;
- }
-
- // Element tests
- //--------------------------------------------------------------------
-
- /**
- * Checks whether the specified element occurs within this range.
- *
- * @param element the element to check for, null returns false
- * @return true if the specified element occurs within this range
- */
- public boolean contains(final T element) {
- if (element == null) {
- return false;
- }
- return comparator.compare(element, minimum) > -1 && comparator.compare(element, maximum) < 1;
- }
-
- /**
- * Checks whether this range is after the specified element.
- *
- * @param element the element to check for, null returns false
- * @return true if this range is entirely after the specified element
- */
- public boolean isAfter(final T element) {
- if (element == null) {
- return false;
- }
- return comparator.compare(element, minimum) < 0;
- }
-
- /**
- * Checks whether this range starts with the specified element.
- *
- * @param element the element to check for, null returns false
- * @return true if the specified element occurs within this range
- */
- public boolean isStartedBy(final T element) {
- if (element == null) {
- return false;
- }
- return comparator.compare(element, minimum) == 0;
- }
-
- /**
- * Checks whether this range ends with the specified element.
- *
- * @param element the element to check for, null returns false
- * @return true if the specified element occurs within this range
- */
- public boolean isEndedBy(final T element) {
- if (element == null) {
- return false;
- }
- return comparator.compare(element, maximum) == 0;
- }
-
- /**
- * Checks whether this range is before the specified element.
- *
- * @param element the element to check for, null returns false
- * @return true if this range is entirely before the specified element
- */
- public boolean isBefore(final T element) {
- if (element == null) {
- return false;
- }
- return comparator.compare(element, maximum) > 0;
- }
-
- /**
- * Checks where the specified element occurs relative to this range.
- *
- * The API is reminiscent of the Comparable interface returning {@code -1} if
- * the element is before the range, {@code 0} if contained within the range and
- * {@code 1} if the element is after the range.
- *
- * @param element the element to check for, not null
- * @return -1, 0 or +1 depending on the element's location relative to the range
- */
- public int elementCompareTo(final T element) {
- // Comparable API says throw NPE on null
- Validate.notNull(element, "Element is null");
- if (isAfter(element)) {
- return -1;
- } else if (isBefore(element)) {
- return 1;
- } else {
- return 0;
- }
- }
-
- // Range tests
- //--------------------------------------------------------------------
-
- /**
- * Checks whether this range contains all the elements of the specified range.
- *
- * This method may fail if the ranges have two different comparators or element types.
- *
- * @param otherRange the range to check, null returns false
- * @return true if this range contains the specified range
- * @throws RuntimeException if ranges cannot be compared
- */
- public boolean containsRange(final Range otherRange) {
- if (otherRange == null) {
- return false;
- }
- return contains(otherRange.minimum)
- && contains(otherRange.maximum);
- }
-
- /**
- * Checks whether this range is completely after the specified range.
- *
- * This method may fail if the ranges have two different comparators or element types.
- *
- * @param otherRange the range to check, null returns false
- * @return true if this range is completely after the specified range
- * @throws RuntimeException if ranges cannot be compared
- */
- public boolean isAfterRange(final Range otherRange) {
- if (otherRange == null) {
- return false;
- }
- return isAfter(otherRange.maximum);
- }
-
- /**
- * Checks whether this range is overlapped by the specified range.
- *
- * Two ranges overlap if there is at least one element in common.
- *
- * This method may fail if the ranges have two different comparators or element types.
- *
- * @param otherRange the range to test, null returns false
- * @return true if the specified range overlaps with this
- * range; otherwise, {@code false}
- * @throws RuntimeException if ranges cannot be compared
- */
- public boolean isOverlappedBy(final Range otherRange) {
- if (otherRange == null) {
- return false;
- }
- return otherRange.contains(minimum)
- || otherRange.contains(maximum)
- || contains(otherRange.minimum);
- }
-
- /**
- * Checks whether this range is completely before the specified range.
- *
- * This method may fail if the ranges have two different comparators or element types.
- *
- * @param otherRange the range to check, null returns false
- * @return true if this range is completely before the specified range
- * @throws RuntimeException if ranges cannot be compared
- */
- public boolean isBeforeRange(final Range otherRange) {
- if (otherRange == null) {
- return false;
- }
- return isBefore(otherRange.minimum);
- }
-
- /**
- * Calculate the intersection of {@code this} and an overlapping Range.
- * @param other overlapping Range
- * @return range representing the intersection of {@code this} and {@code other} ({@code this} if equal)
- * @throws IllegalArgumentException if {@code other} does not overlap {@code this}
- * @since 3.0.1
- */
- public Range intersectionWith(final Range other) {
- if (!this.isOverlappedBy(other)) {
- throw new IllegalArgumentException(String.format(
- "Cannot calculate intersection with non-overlapping range %s", other));
- }
- if (this.equals(other)) {
- return this;
- }
- final T min = getComparator().compare(minimum, other.minimum) < 0 ? other.minimum : minimum;
- final T max = getComparator().compare(maximum, other.maximum) < 0 ? maximum : other.maximum;
- return between(min, max, getComparator());
- }
-
- // Basics
- //--------------------------------------------------------------------
-
- /**
- * Compares this range to another object to test if they are equal.
.
- *
- * To be equal, the minimum and maximum values must be equal, which
- * ignores any differences in the comparator.
- *
- * @param obj the reference object with which to compare
- * @return true if this object is equal
- */
- @Override
- public boolean equals(final Object obj) {
- if (obj == this) {
- return true;
- } else if (obj == null || obj.getClass() != getClass()) {
- return false;
- } else {
- @SuppressWarnings("unchecked") // OK because we checked the class above
- final
- Range range = (Range) obj;
- return minimum.equals(range.minimum) &&
- maximum.equals(range.maximum);
- }
- }
-
- /**
- * Gets a suitable hash code for the range.
- *
- * @return a hash code value for this object
- */
- @Override
- public int hashCode() {
- int result = hashCode;
- if (hashCode == 0) {
- result = 17;
- result = 37 * result + getClass().hashCode();
- result = 37 * result + minimum.hashCode();
- result = 37 * result + maximum.hashCode();
- hashCode = result;
- }
- return result;
- }
-
- /**
- * Gets the range as a {@code String}.
- *
- * The format of the String is '[min ..max ]'.
- *
- * @return the {@code String} representation of this range
- */
- @Override
- public String toString() {
- if (toString == null) {
- toString = "[" + minimum + ".." + maximum + "]";
- }
- return toString;
- }
-
- /**
- * Formats the receiver using the given format.
- *
- * This uses {@link java.util.Formattable} to perform the formatting. Three variables may
- * be used to embed the minimum, maximum and comparator.
- * Use {@code %1$s} for the minimum element, {@code %2$s} for the maximum element
- * and {@code %3$s} for the comparator.
- * The default format used by {@code toString()} is {@code [%1$s..%2$s]}.
- *
- * @param format the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null
- * @return the formatted string, not null
- */
- public String toString(final String format) {
- return String.format(format, minimum, maximum, comparator);
- }
-
- //-----------------------------------------------------------------------
- @SuppressWarnings({"rawtypes", "unchecked"})
- private enum ComparableComparator implements Comparator {
- INSTANCE;
- /**
- * Comparable based compare implementation.
- *
- * @param obj1 left hand side of comparison
- * @param obj2 right hand side of comparison
- * @return negative, 0, positive comparison value
- */
- @Override
- public int compare(final Object obj1, final Object obj2) {
- return ((Comparable) obj1).compareTo(obj2);
- }
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ReflectionToStringBuilder.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ReflectionToStringBuilder.java
deleted file mode 100644
index e6edf268..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ReflectionToStringBuilder.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-public class ReflectionToStringBuilder extends ToStringBuilder {
-
- public static String toString(final Object object) {
- return toString(object, null, false, false, null);
- }
-
- public static String toString(final Object object, final ToStringStyle style) {
- return toString(object, style, false, false, null);
- }
-
-
- public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients) {
- return toString(object, style, outputTransients, false, null);
- }
-
-
- public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients, final boolean outputStatics) {
- return toString(object, style, outputTransients, outputStatics, null);
- }
-
-
- public static String toString(
- final T object, final ToStringStyle style, final boolean outputTransients,
- final boolean outputStatics, final Class super T> reflectUpToClass) {
- return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
- .toString();
- }
-
-
- public static String toString(
- final T object, final ToStringStyle style, final boolean outputTransients,
- final boolean outputStatics, final boolean excludeNullValues, final Class super T> reflectUpToClass) {
- return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics, excludeNullValues)
- .toString();
- }
-
-
- public static String toStringExclude(final Object object, final Collection excludeFieldNames) {
- return toStringExclude(object, toNoNullStringArray(excludeFieldNames));
- }
-
-
- static String[] toNoNullStringArray(final Collection collection) {
- if (collection == null) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- return toNoNullStringArray(collection.toArray());
- }
-
-
- static String[] toNoNullStringArray(final Object[] array) {
- final List list = new ArrayList<>(array.length);
- for (final Object e : array) {
- if (e != null) {
- list.add(e.toString());
- }
- }
- return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
- }
-
-
-
- public static String toStringExclude(final Object object, final String... excludeFieldNames) {
- return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString();
- }
-
- private static Object checkNotNull(final Object obj) {
- Validate.isTrue(obj != null, "The Object passed in should not be null.");
- return obj;
- }
-
-
- private boolean appendStatics = false;
-
- /**
- * Whether or not to append transient fields.
- */
- private boolean appendTransients = false;
-
- /**
- * Whether or not to append fields that are null.
- */
- private boolean excludeNullValues;
-
- /**
- * Which field names to exclude from output. Intended for fields like "password".
- *
- * @since 3.0 this is protected instead of private
- */
- protected String[] excludeFieldNames;
-
- /**
- * The last super class to stop appending fields for.
- */
- private Class> upToClass = null;
-
- /**
- *
- * Constructor.
- *
- *
- *
- * This constructor outputs using the default style set with setDefaultStyle.
- *
- *
- * @param object
- * the Object to build a toString for, must not be null
- * @throws IllegalArgumentException
- * if the Object passed in is null
- */
- public ReflectionToStringBuilder(final Object object) {
- super(checkNotNull(object));
- }
-
- /**
- *
- * Constructor.
- *
- *
- *
- * If the style is null, the default style is used.
- *
- *
- * @param object
- * the Object to build a toString for, must not be null
- * @param style
- * the style of the toString to create, may be null
- * @throws IllegalArgumentException
- * if the Object passed in is null
- */
- public ReflectionToStringBuilder(final Object object, final ToStringStyle style) {
- super(checkNotNull(object), style);
- }
-
- /**
- *
- * Constructor.
- *
- *
- *
- * If the style is null, the default style is used.
- *
- *
- *
- * If the buffer is null, a new one is created.
- *
- *
- * @param object
- * the Object to build a toString for
- * @param style
- * the style of the toString to create, may be null
- * @param buffer
- * the StringBuffer to populate, may be null
- * @throws IllegalArgumentException
- * if the Object passed in is null
- */
- public ReflectionToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) {
- super(checkNotNull(object), style, buffer);
- }
-
- /**
- * Constructor.
- *
- * @param
- * the type of the object
- * @param object
- * the Object to build a toString for
- * @param style
- * the style of the toString to create, may be null
- * @param buffer
- * the StringBuffer to populate, may be null
- * @param reflectUpToClass
- * the superclass to reflect up to (inclusive), may be null
- * @param outputTransients
- * whether to include transient fields
- * @param outputStatics
- * whether to include static fields
- * @since 2.1
- */
- public ReflectionToStringBuilder(
- final T object, final ToStringStyle style, final StringBuffer buffer,
- final Class super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics) {
- super(checkNotNull(object), style, buffer);
- this.setUpToClass(reflectUpToClass);
- this.setAppendTransients(outputTransients);
- this.setAppendStatics(outputStatics);
- }
-
- /**
- * Constructor.
- *
- * @param
- * the type of the object
- * @param object
- * the Object to build a toString for
- * @param style
- * the style of the toString to create, may be null
- * @param buffer
- * the StringBuffer to populate, may be null
- * @param reflectUpToClass
- * the superclass to reflect up to (inclusive), may be null
- * @param outputTransients
- * whether to include transient fields
- * @param outputStatics
- * whether to include static fields
- * @param excludeNullValues
- * whether to exclude fields who value is null
- * @since 3.6
- */
- public ReflectionToStringBuilder(
- final T object, final ToStringStyle style, final StringBuffer buffer,
- final Class super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics,
- final boolean excludeNullValues) {
- super(checkNotNull(object), style, buffer);
- this.setUpToClass(reflectUpToClass);
- this.setAppendTransients(outputTransients);
- this.setAppendStatics(outputStatics);
- this.setExcludeNullValues(excludeNullValues);
- }
-
- /**
- * Returns whether or not to append the given Field.
- *
- * Transient fields are appended only if {@link #isAppendTransients()} returns true.
- * Static fields are appended only if {@link #isAppendStatics()} returns true.
- * Inner class fields are not appended.
- *
- *
- * @param field
- * The Field to test.
- * @return Whether or not to append the given Field.
- */
- protected boolean accept(final Field field) {
- if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) {
- // Reject field from inner class.
- return false;
- }
- if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
- // Reject transient fields.
- return false;
- }
- if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
- // Reject static fields.
- return false;
- }
- if (this.excludeFieldNames != null
- && Arrays.binarySearch(this.excludeFieldNames, field.getName()) >= 0) {
- // Reject fields from the getExcludeFieldNames list.
- return false;
- }
- return !field.isAnnotationPresent(ToStringExclude.class);
- }
-
- /**
- *
- * Appends the fields and values defined by the given object of the given Class.
- *
- *
- *
- * If a cycle is detected as an object is "toString()'ed", such an object is rendered as if
- * Object.toString() had been called and not implemented by the object.
- *
- *
- * @param clazz
- * The class of object parameter
- */
- protected void appendFieldsIn(final Class> clazz) {
- if (clazz.isArray()) {
- this.reflectionAppendArray(this.getObject());
- return;
- }
- final Field[] fields = clazz.getDeclaredFields();
- AccessibleObject.setAccessible(fields, true);
- for (final Field field : fields) {
- final String fieldName = field.getName();
- if (this.accept(field)) {
- try {
- // Warning: Field.get(Object) creates wrappers objects
- // for primitive types.
- final Object fieldValue = this.getValue(field);
- if (!excludeNullValues || fieldValue != null) {
- this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class));
- }
- } catch (final IllegalAccessException ex) {
- //this can't happen. Would get a Security exception
- // instead
- //throw a runtime exception in case the impossible
- // happens.
- throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
- }
- }
- }
- }
-
- /**
- * @return Returns the excludeFieldNames.
- */
- public String[] getExcludeFieldNames() {
- return this.excludeFieldNames.clone();
- }
-
- /**
- *
- * Gets the last super class to stop appending fields for.
- *
- *
- * @return The last super class to stop appending fields for.
- */
- public Class> getUpToClass() {
- return this.upToClass;
- }
-
- /**
- *
- * Calls java.lang.reflect.Field.get(Object).
- *
- *
- * @param field
- * The Field to query.
- * @return The Object from the given Field.
- *
- * @throws IllegalArgumentException
- * see {@link Field#get(Object)}
- * @throws IllegalAccessException
- * see {@link Field#get(Object)}
- *
- * @see Field#get(Object)
- */
- protected Object getValue(final Field field) throws IllegalAccessException {
- return field.get(this.getObject());
- }
-
- /**
- *
- * Gets whether or not to append static fields.
- *
- *
- * @return Whether or not to append static fields.
- * @since 2.1
- */
- public boolean isAppendStatics() {
- return this.appendStatics;
- }
-
- /**
- *
- * Gets whether or not to append transient fields.
- *
- *
- * @return Whether or not to append transient fields.
- */
- public boolean isAppendTransients() {
- return this.appendTransients;
- }
-
- /**
- *
- * Gets whether or not to append fields whose values are null.
- *
- *
- * @return Whether or not to append fields whose values are null.
- * @since 3.6
- */
- public boolean isExcludeNullValues() {
- return this.excludeNullValues;
- }
-
- /**
- *
- * Append to the toString an Object array.
- *
- *
- * @param array
- * the array to add to the toString
- * @return this
- */
- public ReflectionToStringBuilder reflectionAppendArray(final Object array) {
- this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
- return this;
- }
-
- /**
- *
- * Sets whether or not to append static fields.
- *
- *
- * @param appendStatics
- * Whether or not to append static fields.
- * @since 2.1
- */
- public void setAppendStatics(final boolean appendStatics) {
- this.appendStatics = appendStatics;
- }
-
- /**
- *
- * Sets whether or not to append transient fields.
- *
- *
- * @param appendTransients
- * Whether or not to append transient fields.
- */
- public void setAppendTransients(final boolean appendTransients) {
- this.appendTransients = appendTransients;
- }
-
- /**
- *
- * Sets whether or not to append fields whose values are null.
- *
- *
- * @param excludeNullValues
- * Whether or not to append fields whose values are null.
- * @since 3.6
- */
- public void setExcludeNullValues(final boolean excludeNullValues) {
- this.excludeNullValues = excludeNullValues;
- }
-
- /**
- * Sets the field names to exclude.
- *
- * @param excludeFieldNamesParam
- * The excludeFieldNames to excluding from toString or null.
- * @return this
- */
- public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) {
- if (excludeFieldNamesParam == null) {
- this.excludeFieldNames = null;
- } else {
- //clone and remove nulls
- this.excludeFieldNames = toNoNullStringArray(excludeFieldNamesParam);
- Arrays.sort(this.excludeFieldNames);
- }
- return this;
- }
-
- /**
- *
- * Sets the last super class to stop appending fields for.
- *
- *
- * @param clazz
- * The last super class to stop appending fields for.
- */
- public void setUpToClass(final Class> clazz) {
- if (clazz != null) {
- final Object object = getObject();
- if (object != null && !clazz.isInstance(object)) {
- throw new IllegalArgumentException("Specified class is not a superclass of the object");
- }
- }
- this.upToClass = clazz;
- }
-
- /**
- *
- * Gets the String built by this builder.
- *
- *
- * @return the built string
- */
- @Override
- public String toString() {
- if (this.getObject() == null) {
- return this.getStyle().getNullText();
- }
- Class> clazz = this.getObject().getClass();
- this.appendFieldsIn(clazz);
- while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
- clazz = clazz.getSuperclass();
- this.appendFieldsIn(clazz);
- }
- return super.toString();
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/RegExUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/RegExUtils.java
deleted file mode 100644
index 504893f2..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/RegExUtils.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.util.regex.Pattern;
-
-/**
- * Helpers to process Strings using regular expressions.
- * @see Pattern
- * @since 3.8
- */
-public class RegExUtils {
-
- /**
- * Removes each substring of the text String that matches the given regular expression pattern.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.removeAll(null, *) = null
- * StringUtils.removeAll("any", (Pattern) null) = "any"
- * StringUtils.removeAll("any", Pattern.compile("")) = "any"
- * StringUtils.removeAll("any", Pattern.compile(".*")) = ""
- * StringUtils.removeAll("any", Pattern.compile(".+")) = ""
- * StringUtils.removeAll("abc", Pattern.compile(".?")) = ""
- * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\nB"
- * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB"
- * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL)) = "AB"
- * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]")) = "ABC123"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression to which this string is to be matched
- * @return the text with any removes processed,
- * {@code null} if null String input
- *
- * @see #replaceAll(String, Pattern, String)
- * @see java.util.regex.Matcher#replaceAll(String)
- * @see Pattern
- */
- public static String removeAll(final String text, final Pattern regex) {
- return replaceAll(text, regex, StringUtils.EMPTY);
- }
-
- /**
- * Removes each substring of the text String that matches the given regular expression.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll(regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
- * is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.removeAll(null, *) = null
- * StringUtils.removeAll("any", (String) null) = "any"
- * StringUtils.removeAll("any", "") = "any"
- * StringUtils.removeAll("any", ".*") = ""
- * StringUtils.removeAll("any", ".+") = ""
- * StringUtils.removeAll("abc", ".?") = ""
- * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB"
- * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB"
- * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression to which this string is to be matched
- * @return the text with any removes processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replaceAll(String, String, String)
- * @see #removePattern(String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- */
- public static String removeAll(final String text, final String regex) {
- return replaceAll(text, regex, StringUtils.EMPTY);
- }
-
- /**
- * Removes the first substring of the text string that matches the given regular expression pattern.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code pattern.matcher(text).replaceFirst(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.removeFirst(null, *) = null
- * StringUtils.removeFirst("any", (Pattern) null) = "any"
- * StringUtils.removeFirst("any", Pattern.compile("")) = "any"
- * StringUtils.removeFirst("any", Pattern.compile(".*")) = ""
- * StringUtils.removeFirst("any", Pattern.compile(".+")) = ""
- * StringUtils.removeFirst("abc", Pattern.compile(".?")) = "bc"
- * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\n<__>B"
- * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB"
- * StringUtils.removeFirst("ABCabc123", Pattern.compile("[a-z]")) = "ABCbc123"
- * StringUtils.removeFirst("ABCabc123abc", Pattern.compile("[a-z]+")) = "ABC123abc"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression pattern to which this string is to be matched
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @see #replaceFirst(String, Pattern, String)
- * @see java.util.regex.Matcher#replaceFirst(String)
- * @see Pattern
- */
- public static String removeFirst(final String text, final Pattern regex) {
- return replaceFirst(text, regex, StringUtils.EMPTY);
- }
-
- /**
- * Removes the first substring of the text string that matches the given regular expression.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceFirst(regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * The {@link Pattern#DOTALL} option is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.removeFirst(null, *) = null
- * StringUtils.removeFirst("any", (String) null) = "any"
- * StringUtils.removeFirst("any", "") = "any"
- * StringUtils.removeFirst("any", ".*") = ""
- * StringUtils.removeFirst("any", ".+") = ""
- * StringUtils.removeFirst("abc", ".?") = "bc"
- * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B"
- * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB"
- * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123"
- * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression to which this string is to be matched
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replaceFirst(String, String, String)
- * @see String#replaceFirst(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- */
- public static String removeFirst(final String text, final String regex) {
- return replaceFirst(text, regex, StringUtils.EMPTY);
- }
-
- /**
- * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
- *
- * This call is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll("(?s)" + regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.removePattern(null, *) = null
- * StringUtils.removePattern("any", (String) null) = "any"
- * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB"
- * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123"
- *
- *
- * @param text
- * the source string
- * @param regex
- * the regular expression to which this string is to be matched
- * @return The resulting {@code String}
- * @see #replacePattern(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern#DOTALL
- */
- public static String removePattern(final String text, final String regex) {
- return replacePattern(text, regex, StringUtils.EMPTY);
- }
-
- /**
- * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code pattern.matcher(text).replaceAll(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceAll(null, *, *) = null
- * StringUtils.replaceAll("any", (Pattern) null, *) = "any"
- * StringUtils.replaceAll("any", *, null) = "any"
- * StringUtils.replaceAll("", Pattern.compile(""), "zzz") = "zzz"
- * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz") = "zzz"
- * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz") = ""
- * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ") = "ZZaZZbZZcZZ"
- * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\nz"
- * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z"
- * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z"
- * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC___123"
- * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123"
- * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123"
- * StringUtils.replaceAll("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum_dolor_sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression pattern to which this string is to be matched
- * @param replacement the string to be substituted for each match
- * @return the text with any replacements processed,
- * {@code null} if null String input
- *
- * @see java.util.regex.Matcher#replaceAll(String)
- * @see Pattern
- */
- public static String replaceAll(final String text, final Pattern regex, final String replacement) {
- if (text == null || regex == null || replacement == null) {
- return text;
- }
- return regex.matcher(text).replaceAll(replacement);
- }
-
- /**
- * Replaces each substring of the text String that matches the given regular expression
- * with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll(regex, replacement)}
- * {@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
- * is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.replaceAll(null, *, *) = null
- * StringUtils.replaceAll("any", (String) null, *) = "any"
- * StringUtils.replaceAll("any", *, null) = "any"
- * StringUtils.replaceAll("", "", "zzz") = "zzz"
- * StringUtils.replaceAll("", ".*", "zzz") = "zzz"
- * StringUtils.replaceAll("", ".+", "zzz") = ""
- * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ"
- * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz"
- * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z"
- * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123"
- * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
- * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
- * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression to which this string is to be matched
- * @param replacement the string to be substituted for each match
- * @return the text with any replacements processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replacePattern(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- */
- public static String replaceAll(final String text, final String regex, final String replacement) {
- if (text == null || regex == null || replacement == null) {
- return text;
- }
- return text.replaceAll(regex, replacement);
- }
-
- /**
- * Replaces the first substring of the text string that matches the given regular expression pattern
- * with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code pattern.matcher(text).replaceFirst(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceFirst(null, *, *) = null
- * StringUtils.replaceFirst("any", (Pattern) null, *) = "any"
- * StringUtils.replaceFirst("any", *, null) = "any"
- * StringUtils.replaceFirst("", Pattern.compile(""), "zzz") = "zzz"
- * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz") = "zzz"
- * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz") = ""
- * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ") = "ZZabc"
- * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\n<__>"
- * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z"
- * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC_bc123"
- * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123abc"
- * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123abc"
- * StringUtils.replaceFirst("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum dolor sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression pattern to which this string is to be matched
- * @param replacement the string to be substituted for the first match
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @see java.util.regex.Matcher#replaceFirst(String)
- * @see Pattern
- */
- public static String replaceFirst(final String text, final Pattern regex, final String replacement) {
- if (text == null || regex == null|| replacement == null ) {
- return text;
- }
- return regex.matcher(text).replaceFirst(replacement);
- }
-
- /**
- * Replaces the first substring of the text string that matches the given regular expression
- * with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceFirst(regex, replacement)}
- * {@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * The {@link Pattern#DOTALL} option is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.replaceFirst(null, *, *) = null
- * StringUtils.replaceFirst("any", (String) null, *) = "any"
- * StringUtils.replaceFirst("any", *, null) = "any"
- * StringUtils.replaceFirst("", "", "zzz") = "zzz"
- * StringUtils.replaceFirst("", ".*", "zzz") = "zzz"
- * StringUtils.replaceFirst("", ".+", "zzz") = ""
- * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc"
- * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>"
- * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z"
- * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123"
- * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc"
- * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc"
- * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression to which this string is to be matched
- * @param replacement the string to be substituted for the first match
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see String#replaceFirst(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- */
- public static String replaceFirst(final String text, final String regex, final String replacement) {
- if (text == null || regex == null|| replacement == null ) {
- return text;
- }
- return text.replaceFirst(regex, replacement);
- }
-
- /**
- * Replaces each substring of the source String that matches the given regular expression with the given
- * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
- *
- * This call is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll("(?s)" + regex, replacement)}
- * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replacePattern(null, *, *) = null
- * StringUtils.replacePattern("any", (String) null, *) = "any"
- * StringUtils.replacePattern("any", *, null) = "any"
- * StringUtils.replacePattern("", "", "zzz") = "zzz"
- * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
- * StringUtils.replacePattern("", ".+", "zzz") = ""
- * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
- * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
- * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
- * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
- * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
- *
- *
- * @param text
- * the source string
- * @param regex
- * the regular expression to which this string is to be matched
- * @param replacement
- * the string to be substituted for each match
- * @return The resulting {@code String}
- * @see #replaceAll(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern#DOTALL
- */
- public static String replacePattern(final String text, final String regex, final String replacement) {
- if (text == null || regex == null || replacement == null) {
- return text;
- }
- return Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement);
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrBuilder.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrBuilder.java
deleted file mode 100644
index 89c329dd..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrBuilder.java
+++ /dev/null
@@ -1,3099 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Serializable;
-import java.io.Writer;
-import java.nio.CharBuffer;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Builds a string from constituent parts providing a more flexible and powerful API
- * than StringBuffer.
- *
- * The main differences from StringBuffer/StringBuilder are:
- *
- *
- * Not synchronized
- * Not final
- * Subclasses have direct access to character array
- * Additional methods
- *
- * appendWithSeparators - adds an array of values, with a separator
- * appendPadding - adds a length padding characters
- * appendFixedLength - adds a fixed width field to the builder
- * toCharArray/getChars - simpler ways to get a range of the character array
- * delete - delete char or string
- * replace - search and replace for a char or string
- * leftString/rightString/midString - substring without exceptions
- * contains - whether the builder contains a char or string
- * size/clear/isEmpty - collections style API methods
- *
- *
- * Views
- *
- * asTokenizer - uses the internal buffer as the source of a StrTokenizer
- * asReader - uses the internal buffer as the source of a Reader
- * asWriter - allows a Writer to write directly to the internal buffer
- *
- *
- *
- *
- * The aim has been to provide an API that mimics very closely what StringBuffer
- * provides, but with additional methods. It should be noted that some edge cases,
- * with invalid indices or null input, have been altered - see individual methods.
- * The biggest of these changes is that by default, null will not output the text
- * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
- *
- * Prior to 3.0, this class implemented Cloneable but did not implement the
- * clone method so could not be used. From 3.0 onwards it no longer implements
- * the interface.
- *
- * @since 2.2
- * @deprecated as of 3.6, use commons-text
- *
- * TextStringBuilder instead
- */
-@Deprecated
-public class StrBuilder implements CharSequence, Appendable, Serializable, Builder {
-
- /**
- * The extra capacity for new builders.
- */
- static final int CAPACITY = 32;
-
- /**
- * Required for serialization support.
- *
- * @see Serializable
- */
- private static final long serialVersionUID = 7628716375283629643L;
-
- /** Internal data storage. */
- protected char[] buffer; // TODO make private?
- /** Current size of the buffer. */
- protected int size; // TODO make private?
- /** The new line. */
- private String newLine;
- /** The null text. */
- private String nullText;
-
- //-----------------------------------------------------------------------
- /**
- * Constructor that creates an empty builder initial capacity 32 characters.
- */
- public StrBuilder() {
- this(CAPACITY);
- }
-
- /**
- * Constructor that creates an empty builder the specified initial capacity.
- *
- * @param initialCapacity the initial capacity, zero or less will be converted to 32
- */
- public StrBuilder(int initialCapacity) {
- super();
- if (initialCapacity <= 0) {
- initialCapacity = CAPACITY;
- }
- buffer = new char[initialCapacity];
- }
-
- /**
- * Constructor that creates a builder from the string, allocating
- * 32 extra characters for growth.
- *
- * @param str the string to copy, null treated as blank string
- */
- public StrBuilder(final String str) {
- super();
- if (str == null) {
- buffer = new char[CAPACITY];
- } else {
- buffer = new char[str.length() + CAPACITY];
- append(str);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the text to be appended when a new line is added.
- *
- * @return the new line text, null means use system default
- */
- public String getNewLineText() {
- return newLine;
- }
-
- /**
- * Sets the text to be appended when a new line is added.
- *
- * @param newLine the new line text, null means use system default
- * @return this, to enable chaining
- */
- public StrBuilder setNewLineText(final String newLine) {
- this.newLine = newLine;
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the text to be appended when null is added.
- *
- * @return the null text, null means no append
- */
- public String getNullText() {
- return nullText;
- }
-
- /**
- * Sets the text to be appended when null is added.
- *
- * @param nullText the null text, null means no append
- * @return this, to enable chaining
- */
- public StrBuilder setNullText(String nullText) {
- if (nullText != null && nullText.isEmpty()) {
- nullText = null;
- }
- this.nullText = nullText;
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the length of the string builder.
- *
- * @return the length
- */
- @Override
- public int length() {
- return size;
- }
-
- /**
- * Updates the length of the builder by either dropping the last characters
- * or adding filler of Unicode zero.
- *
- * @param length the length to set to, must be zero or positive
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the length is negative
- */
- public StrBuilder setLength(final int length) {
- if (length < 0) {
- throw new StringIndexOutOfBoundsException(length);
- }
- if (length < size) {
- size = length;
- } else if (length > size) {
- ensureCapacity(length);
- final int oldEnd = size;
- final int newEnd = length;
- size = length;
- for (int i = oldEnd; i < newEnd; i++) {
- buffer[i] = CharUtils.NUL;
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the current size of the internal character array buffer.
- *
- * @return the capacity
- */
- public int capacity() {
- return buffer.length;
- }
-
- /**
- * Checks the capacity and ensures that it is at least the size specified.
- *
- * @param capacity the capacity to ensure
- * @return this, to enable chaining
- */
- public StrBuilder ensureCapacity(final int capacity) {
- if (capacity > buffer.length) {
- final char[] old = buffer;
- buffer = new char[capacity * 2];
- System.arraycopy(old, 0, buffer, 0, size);
- }
- return this;
- }
-
- /**
- * Minimizes the capacity to the actual length of the string.
- *
- * @return this, to enable chaining
- */
- public StrBuilder minimizeCapacity() {
- if (buffer.length > length()) {
- final char[] old = buffer;
- buffer = new char[length()];
- System.arraycopy(old, 0, buffer, 0, size);
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the length of the string builder.
- *
- * This method is the same as {@link #length()} and is provided to match the
- * API of Collections.
- *
- * @return the length
- */
- public int size() {
- return size;
- }
-
- /**
- * Checks is the string builder is empty (convenience Collections API style method).
- *
- * This method is the same as checking {@link #length()} and is provided to match the
- * API of Collections.
- *
- * @return true if the size is 0.
- */
- public boolean isEmpty() {
- return size == 0;
- }
-
- /**
- * Clears the string builder (convenience Collections API style method).
- *
- * This method does not reduce the size of the internal character buffer.
- * To do that, call clear() followed by {@link #minimizeCapacity()}.
- *
- * This method is the same as {@link #setLength(int)} called with zero
- * and is provided to match the API of Collections.
- *
- * @return this, to enable chaining
- */
- public StrBuilder clear() {
- size = 0;
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the character at the specified index.
- *
- * @see #setCharAt(int, char)
- * @see #deleteCharAt(int)
- * @param index the index to retrieve, must be valid
- * @return the character at the index
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- @Override
- public char charAt(final int index) {
- if (index < 0 || index >= length()) {
- throw new StringIndexOutOfBoundsException(index);
- }
- return buffer[index];
- }
-
- /**
- * Sets the character at the specified index.
- *
- * @see #charAt(int)
- * @see #deleteCharAt(int)
- * @param index the index to set
- * @param ch the new character
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder setCharAt(final int index, final char ch) {
- if (index < 0 || index >= length()) {
- throw new StringIndexOutOfBoundsException(index);
- }
- buffer[index] = ch;
- return this;
- }
-
- /**
- * Deletes the character at the specified index.
- *
- * @see #charAt(int)
- * @see #setCharAt(int, char)
- * @param index the index to delete
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder deleteCharAt(final int index) {
- if (index < 0 || index >= size) {
- throw new StringIndexOutOfBoundsException(index);
- }
- deleteImpl(index, index + 1, 1);
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Copies the builder's character array into a new character array.
- *
- * @return a new array that represents the contents of the builder
- */
- public char[] toCharArray() {
- if (size == 0) {
- return ArrayUtils.EMPTY_CHAR_ARRAY;
- }
- final char chars[] = new char[size];
- System.arraycopy(buffer, 0, chars, 0, size);
- return chars;
- }
-
- /**
- * Copies part of the builder's character array into a new character array.
- *
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except that
- * if too large it is treated as end of string
- * @return a new array that holds part of the contents of the builder
- * @throws IndexOutOfBoundsException if startIndex is invalid,
- * or if endIndex is invalid (but endIndex greater than size is valid)
- */
- public char[] toCharArray(final int startIndex, int endIndex) {
- endIndex = validateRange(startIndex, endIndex);
- final int len = endIndex - startIndex;
- if (len == 0) {
- return ArrayUtils.EMPTY_CHAR_ARRAY;
- }
- final char chars[] = new char[len];
- System.arraycopy(buffer, startIndex, chars, 0, len);
- return chars;
- }
-
- /**
- * Copies the character array into the specified array.
- *
- * @param destination the destination array, null will cause an array to be created
- * @return the input array, unless that was null or too small
- */
- public char[] getChars(char[] destination) {
- final int len = length();
- if (destination == null || destination.length < len) {
- destination = new char[len];
- }
- System.arraycopy(buffer, 0, destination, 0, len);
- return destination;
- }
-
- /**
- * Copies the character array into the specified array.
- *
- * @param startIndex first index to copy, inclusive, must be valid
- * @param endIndex last index, exclusive, must be valid
- * @param destination the destination array, must not be null or too small
- * @param destinationIndex the index to start copying in destination
- * @throws NullPointerException if the array is null
- * @throws IndexOutOfBoundsException if any index is invalid
- */
- public void getChars(final int startIndex, final int endIndex, final char destination[], final int destinationIndex) {
- if (startIndex < 0) {
- throw new StringIndexOutOfBoundsException(startIndex);
- }
- if (endIndex < 0 || endIndex > length()) {
- throw new StringIndexOutOfBoundsException(endIndex);
- }
- if (startIndex > endIndex) {
- throw new StringIndexOutOfBoundsException("end < start");
- }
- System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
- }
-
- //-----------------------------------------------------------------------
- /**
- * If possible, reads chars from the provided {@link Readable} directly into underlying
- * character buffer without making extra copies.
- *
- * @param readable object to read from
- * @return the number of characters read
- * @throws IOException if an I/O error occurs
- *
- * @since 3.4
- * @see #appendTo(Appendable)
- */
- public int readFrom(final Readable readable) throws IOException {
- final int oldSize = size;
- if (readable instanceof Reader) {
- final Reader r = (Reader) readable;
- ensureCapacity(size + 1);
- int read;
- while ((read = r.read(buffer, size, buffer.length - size)) != -1) {
- size += read;
- ensureCapacity(size + 1);
- }
- } else if (readable instanceof CharBuffer) {
- final CharBuffer cb = (CharBuffer) readable;
- final int remaining = cb.remaining();
- ensureCapacity(size + remaining);
- cb.get(buffer, size, remaining);
- size += remaining;
- } else {
- while (true) {
- ensureCapacity(size + 1);
- final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
- final int read = readable.read(buf);
- if (read == -1) {
- break;
- }
- size += read;
- }
- }
- return size - oldSize;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends the new line string to this string builder.
- *
- * The new line string can be altered using {@link #setNewLineText(String)}.
- * This might be used to force the output to always use Unix line endings
- * even when on Windows.
- *
- * @return this, to enable chaining
- */
- public StrBuilder appendNewLine() {
- if (newLine == null) {
- append(System.lineSeparator());
- return this;
- }
- return append(newLine);
- }
-
- /**
- * Appends the text representing null to this string builder.
- *
- * @return this, to enable chaining
- */
- public StrBuilder appendNull() {
- if (nullText == null) {
- return this;
- }
- return append(nullText);
- }
-
- /**
- * Appends an object to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param obj the object to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final Object obj) {
- if (obj == null) {
- return appendNull();
- }
- if (obj instanceof CharSequence) {
- return append((CharSequence) obj);
- }
- return append(obj.toString());
- }
-
- /**
- * Appends a CharSequence to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param seq the CharSequence to append
- * @return this, to enable chaining
- * @since 3.0
- */
- @Override
- public StrBuilder append(final CharSequence seq) {
- if (seq == null) {
- return appendNull();
- }
- if (seq instanceof StrBuilder) {
- return append((StrBuilder) seq);
- }
- if (seq instanceof StringBuilder) {
- return append((StringBuilder) seq);
- }
- if (seq instanceof StringBuffer) {
- return append((StringBuffer) seq);
- }
- if (seq instanceof CharBuffer) {
- return append((CharBuffer) seq);
- }
- return append(seq.toString());
- }
-
- /**
- * Appends part of a CharSequence to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param seq the CharSequence to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 3.0
- */
- @Override
- public StrBuilder append(final CharSequence seq, final int startIndex, final int length) {
- if (seq == null) {
- return appendNull();
- }
- return append(seq.toString(), startIndex, length);
- }
-
- /**
- * Appends a string to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final String str) {
- if (str == null) {
- return appendNull();
- }
- final int strLen = str.length();
- if (strLen > 0) {
- final int len = length();
- ensureCapacity(len + strLen);
- str.getChars(0, strLen, buffer, len);
- size += strLen;
- }
- return this;
- }
-
-
- /**
- * Appends part of a string to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- */
- public StrBuilder append(final String str, final int startIndex, final int length) {
- if (str == null) {
- return appendNull();
- }
- if (startIndex < 0 || startIndex > str.length()) {
- throw new StringIndexOutOfBoundsException("startIndex must be valid");
- }
- if (length < 0 || (startIndex + length) > str.length()) {
- throw new StringIndexOutOfBoundsException("length must be valid");
- }
- if (length > 0) {
- final int len = length();
- ensureCapacity(len + length);
- str.getChars(startIndex, startIndex + length, buffer, len);
- size += length;
- }
- return this;
- }
-
- /**
- * Calls {@link String#format(String, Object...)} and appends the result.
- *
- * @param format the format string
- * @param objs the objects to use in the format string
- * @return {@code this} to enable chaining
- * @see String#format(String, Object...)
- * @since 3.2
- */
- public StrBuilder append(final String format, final Object... objs) {
- return append(String.format(format, objs));
- }
-
- /**
- * Appends the contents of a char buffer to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param buf the char buffer to append
- * @return this, to enable chaining
- * @since 3.4
- */
- public StrBuilder append(final CharBuffer buf) {
- if (buf == null) {
- return appendNull();
- }
- if (buf.hasArray()) {
- final int length = buf.remaining();
- final int len = length();
- ensureCapacity(len + length);
- System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length);
- size += length;
- } else {
- append(buf.toString());
- }
- return this;
- }
-
- /**
- * Appends the contents of a char buffer to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param buf the char buffer to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 3.4
- */
- public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) {
- if (buf == null) {
- return appendNull();
- }
- if (buf.hasArray()) {
- final int totalLength = buf.remaining();
- if (startIndex < 0 || startIndex > totalLength) {
- throw new StringIndexOutOfBoundsException("startIndex must be valid");
- }
- if (length < 0 || (startIndex + length) > totalLength) {
- throw new StringIndexOutOfBoundsException("length must be valid");
- }
- final int len = length();
- ensureCapacity(len + length);
- System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length);
- size += length;
- } else {
- append(buf.toString(), startIndex, length);
- }
- return this;
- }
-
- /**
- * Appends a string buffer to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string buffer to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final StringBuffer str) {
- if (str == null) {
- return appendNull();
- }
- final int strLen = str.length();
- if (strLen > 0) {
- final int len = length();
- ensureCapacity(len + strLen);
- str.getChars(0, strLen, buffer, len);
- size += strLen;
- }
- return this;
- }
-
- /**
- * Appends part of a string buffer to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- */
- public StrBuilder append(final StringBuffer str, final int startIndex, final int length) {
- if (str == null) {
- return appendNull();
- }
- if (startIndex < 0 || startIndex > str.length()) {
- throw new StringIndexOutOfBoundsException("startIndex must be valid");
- }
- if (length < 0 || (startIndex + length) > str.length()) {
- throw new StringIndexOutOfBoundsException("length must be valid");
- }
- if (length > 0) {
- final int len = length();
- ensureCapacity(len + length);
- str.getChars(startIndex, startIndex + length, buffer, len);
- size += length;
- }
- return this;
- }
-
- /**
- * Appends a StringBuilder to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the StringBuilder to append
- * @return this, to enable chaining
- * @since 3.2
- */
- public StrBuilder append(final StringBuilder str) {
- if (str == null) {
- return appendNull();
- }
- final int strLen = str.length();
- if (strLen > 0) {
- final int len = length();
- ensureCapacity(len + strLen);
- str.getChars(0, strLen, buffer, len);
- size += strLen;
- }
- return this;
- }
-
- /**
- * Appends part of a StringBuilder to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the StringBuilder to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 3.2
- */
- public StrBuilder append(final StringBuilder str, final int startIndex, final int length) {
- if (str == null) {
- return appendNull();
- }
- if (startIndex < 0 || startIndex > str.length()) {
- throw new StringIndexOutOfBoundsException("startIndex must be valid");
- }
- if (length < 0 || (startIndex + length) > str.length()) {
- throw new StringIndexOutOfBoundsException("length must be valid");
- }
- if (length > 0) {
- final int len = length();
- ensureCapacity(len + length);
- str.getChars(startIndex, startIndex + length, buffer, len);
- size += length;
- }
- return this;
- }
-
- /**
- * Appends another string builder to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string builder to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final StrBuilder str) {
- if (str == null) {
- return appendNull();
- }
- final int strLen = str.length();
- if (strLen > 0) {
- final int len = length();
- ensureCapacity(len + strLen);
- System.arraycopy(str.buffer, 0, buffer, len, strLen);
- size += strLen;
- }
- return this;
- }
-
- /**
- * Appends part of a string builder to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- */
- public StrBuilder append(final StrBuilder str, final int startIndex, final int length) {
- if (str == null) {
- return appendNull();
- }
- if (startIndex < 0 || startIndex > str.length()) {
- throw new StringIndexOutOfBoundsException("startIndex must be valid");
- }
- if (length < 0 || (startIndex + length) > str.length()) {
- throw new StringIndexOutOfBoundsException("length must be valid");
- }
- if (length > 0) {
- final int len = length();
- ensureCapacity(len + length);
- str.getChars(startIndex, startIndex + length, buffer, len);
- size += length;
- }
- return this;
- }
-
- /**
- * Appends a char array to the string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param chars the char array to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final char[] chars) {
- if (chars == null) {
- return appendNull();
- }
- final int strLen = chars.length;
- if (strLen > 0) {
- final int len = length();
- ensureCapacity(len + strLen);
- System.arraycopy(chars, 0, buffer, len, strLen);
- size += strLen;
- }
- return this;
- }
-
- /**
- * Appends a char array to the string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param chars the char array to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- */
- public StrBuilder append(final char[] chars, final int startIndex, final int length) {
- if (chars == null) {
- return appendNull();
- }
- if (startIndex < 0 || startIndex > chars.length) {
- throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
- }
- if (length < 0 || (startIndex + length) > chars.length) {
- throw new StringIndexOutOfBoundsException("Invalid length: " + length);
- }
- if (length > 0) {
- final int len = length();
- ensureCapacity(len + length);
- System.arraycopy(chars, startIndex, buffer, len, length);
- size += length;
- }
- return this;
- }
-
- /**
- * Appends a boolean value to the string builder.
- *
- * @param value the value to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final boolean value) {
- if (value) {
- ensureCapacity(size + 4);
- buffer[size++] = 't';
- buffer[size++] = 'r';
- buffer[size++] = 'u';
- buffer[size++] = 'e';
- } else {
- ensureCapacity(size + 5);
- buffer[size++] = 'f';
- buffer[size++] = 'a';
- buffer[size++] = 'l';
- buffer[size++] = 's';
- buffer[size++] = 'e';
- }
- return this;
- }
-
- /**
- * Appends a char value to the string builder.
- *
- * @param ch the value to append
- * @return this, to enable chaining
- * @since 3.0
- */
- @Override
- public StrBuilder append(final char ch) {
- final int len = length();
- ensureCapacity(len + 1);
- buffer[size++] = ch;
- return this;
- }
-
- /**
- * Appends an int value to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final int value) {
- return append(String.valueOf(value));
- }
-
- /**
- * Appends a long value to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final long value) {
- return append(String.valueOf(value));
- }
-
- /**
- * Appends a float value to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final float value) {
- return append(String.valueOf(value));
- }
-
- /**
- * Appends a double value to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- */
- public StrBuilder append(final double value) {
- return append(String.valueOf(value));
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends an object followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param obj the object to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final Object obj) {
- return append(obj).appendNewLine();
- }
-
- /**
- * Appends a string followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final String str) {
- return append(str).appendNewLine();
- }
-
- /**
- * Appends part of a string followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final String str, final int startIndex, final int length) {
- return append(str, startIndex, length).appendNewLine();
- }
-
- /**
- * Calls {@link String#format(String, Object...)} and appends the result.
- *
- * @param format the format string
- * @param objs the objects to use in the format string
- * @return {@code this} to enable chaining
- * @see String#format(String, Object...)
- * @since 3.2
- */
- public StrBuilder appendln(final String format, final Object... objs) {
- return append(format, objs).appendNewLine();
- }
-
- /**
- * Appends a string buffer followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string buffer to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final StringBuffer str) {
- return append(str).appendNewLine();
- }
-
- /**
- * Appends a string builder followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string builder to append
- * @return this, to enable chaining
- * @since 3.2
- */
- public StrBuilder appendln(final StringBuilder str) {
- return append(str).appendNewLine();
- }
-
- /**
- * Appends part of a string builder followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string builder to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 3.2
- */
- public StrBuilder appendln(final StringBuilder str, final int startIndex, final int length) {
- return append(str, startIndex, length).appendNewLine();
- }
-
- /**
- * Appends part of a string buffer followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final StringBuffer str, final int startIndex, final int length) {
- return append(str, startIndex, length).appendNewLine();
- }
-
- /**
- * Appends another string builder followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string builder to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final StrBuilder str) {
- return append(str).appendNewLine();
- }
-
- /**
- * Appends part of a string builder followed by a new line to this string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param str the string to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) {
- return append(str, startIndex, length).appendNewLine();
- }
-
- /**
- * Appends a char array followed by a new line to the string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param chars the char array to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final char[] chars) {
- return append(chars).appendNewLine();
- }
-
- /**
- * Appends a char array followed by a new line to the string builder.
- * Appending null will call {@link #appendNull()}.
- *
- * @param chars the char array to append
- * @param startIndex the start index, inclusive, must be valid
- * @param length the length to append, must be valid
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final char[] chars, final int startIndex, final int length) {
- return append(chars, startIndex, length).appendNewLine();
- }
-
- /**
- * Appends a boolean value followed by a new line to the string builder.
- *
- * @param value the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final boolean value) {
- return append(value).appendNewLine();
- }
-
- /**
- * Appends a char value followed by a new line to the string builder.
- *
- * @param ch the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final char ch) {
- return append(ch).appendNewLine();
- }
-
- /**
- * Appends an int value followed by a new line to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final int value) {
- return append(value).appendNewLine();
- }
-
- /**
- * Appends a long value followed by a new line to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final long value) {
- return append(value).appendNewLine();
- }
-
- /**
- * Appends a float value followed by a new line to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final float value) {
- return append(value).appendNewLine();
- }
-
- /**
- * Appends a double value followed by a new line to the string builder using String.valueOf.
- *
- * @param value the value to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendln(final double value) {
- return append(value).appendNewLine();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends each item in an array to the builder without any separators.
- * Appending a null array will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param the element type
- * @param array the array to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendAll(@SuppressWarnings("unchecked") final T... array) {
- /*
- * @SuppressWarnings used to hide warning about vararg usage. We cannot
- * use @SafeVarargs, since this method is not final. Using @SuppressWarnings
- * is fine, because it isn't inherited by subclasses, so each subclass must
- * vouch for itself whether its use of 'array' is safe.
- */
- if (array != null && array.length > 0) {
- for (final Object element : array) {
- append(element);
- }
- }
- return this;
- }
-
- /**
- * Appends each item in an iterable to the builder without any separators.
- * Appending a null iterable will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param iterable the iterable to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendAll(final Iterable> iterable) {
- if (iterable != null) {
- for (final Object o : iterable) {
- append(o);
- }
- }
- return this;
- }
-
- /**
- * Appends each item in an iterator to the builder without any separators.
- * Appending a null iterator will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param it the iterator to append
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendAll(final Iterator> it) {
- if (it != null) {
- while (it.hasNext()) {
- append(it.next());
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends an array placing separators between each value, but
- * not before the first or after the last.
- * Appending a null array will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param array the array to append
- * @param separator the separator to use, null means no separator
- * @return this, to enable chaining
- */
- public StrBuilder appendWithSeparators(final Object[] array, final String separator) {
- if (array != null && array.length > 0) {
- final String sep = Objects.toString(separator, "");
- append(array[0]);
- for (int i = 1; i < array.length; i++) {
- append(sep);
- append(array[i]);
- }
- }
- return this;
- }
-
- /**
- * Appends an iterable placing separators between each value, but
- * not before the first or after the last.
- * Appending a null iterable will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param iterable the iterable to append
- * @param separator the separator to use, null means no separator
- * @return this, to enable chaining
- */
- public StrBuilder appendWithSeparators(final Iterable> iterable, final String separator) {
- if (iterable != null) {
- final String sep = Objects.toString(separator, "");
- final Iterator> it = iterable.iterator();
- while (it.hasNext()) {
- append(it.next());
- if (it.hasNext()) {
- append(sep);
- }
- }
- }
- return this;
- }
-
- /**
- * Appends an iterator placing separators between each value, but
- * not before the first or after the last.
- * Appending a null iterator will have no effect.
- * Each object is appended using {@link #append(Object)}.
- *
- * @param it the iterator to append
- * @param separator the separator to use, null means no separator
- * @return this, to enable chaining
- */
- public StrBuilder appendWithSeparators(final Iterator> it, final String separator) {
- if (it != null) {
- final String sep = Objects.toString(separator, "");
- while (it.hasNext()) {
- append(it.next());
- if (it.hasNext()) {
- append(sep);
- }
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends a separator if the builder is currently non-empty.
- * Appending a null separator will have no effect.
- * The separator is appended using {@link #append(String)}.
- *
- * This method is useful for adding a separator each time around the
- * loop except the first.
- *
- * for (Iterator it = list.iterator(); it.hasNext(); ) {
- * appendSeparator(",");
- * append(it.next());
- * }
- *
- * Note that for this simple example, you should use
- * {@link #appendWithSeparators(Iterable, String)}.
- *
- * @param separator the separator to use, null means no separator
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendSeparator(final String separator) {
- return appendSeparator(separator, null);
- }
-
- /**
- * Appends one of both separators to the StrBuilder.
- * If the builder is currently empty it will append the defaultIfEmpty-separator
- * Otherwise it will append the standard-separator
- *
- * Appending a null separator will have no effect.
- * The separator is appended using {@link #append(String)}.
- *
- * This method is for example useful for constructing queries
- *
- * StrBuilder whereClause = new StrBuilder();
- * if(searchCommand.getPriority() != null) {
- * whereClause.appendSeparator(" and", " where");
- * whereClause.append(" priority = ?")
- * }
- * if(searchCommand.getComponent() != null) {
- * whereClause.appendSeparator(" and", " where");
- * whereClause.append(" component = ?")
- * }
- * selectClause.append(whereClause)
- *
- *
- * @param standard the separator if builder is not empty, null means no separator
- * @param defaultIfEmpty the separator if builder is empty, null means no separator
- * @return this, to enable chaining
- * @since 2.5
- */
- public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) {
- final String str = isEmpty() ? defaultIfEmpty : standard;
- if (str != null) {
- append(str);
- }
- return this;
- }
-
- /**
- * Appends a separator if the builder is currently non-empty.
- * The separator is appended using {@link #append(char)}.
- *
- * This method is useful for adding a separator each time around the
- * loop except the first.
- *
- * for (Iterator it = list.iterator(); it.hasNext(); ) {
- * appendSeparator(',');
- * append(it.next());
- * }
- *
- * Note that for this simple example, you should use
- * {@link #appendWithSeparators(Iterable, String)}.
- *
- * @param separator the separator to use
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendSeparator(final char separator) {
- if (size() > 0) {
- append(separator);
- }
- return this;
- }
-
- /**
- * Append one of both separators to the builder
- * If the builder is currently empty it will append the defaultIfEmpty-separator
- * Otherwise it will append the standard-separator
- *
- * The separator is appended using {@link #append(char)}.
- * @param standard the separator if builder is not empty
- * @param defaultIfEmpty the separator if builder is empty
- * @return this, to enable chaining
- * @since 2.5
- */
- public StrBuilder appendSeparator(final char standard, final char defaultIfEmpty) {
- if (size() > 0) {
- append(standard);
- } else {
- append(defaultIfEmpty);
- }
- return this;
- }
- /**
- * Appends a separator to the builder if the loop index is greater than zero.
- * Appending a null separator will have no effect.
- * The separator is appended using {@link #append(String)}.
- *
- * This method is useful for adding a separator each time around the
- * loop except the first.
- *
- *
- * for (int i = 0; i < list.size(); i++) {
- * appendSeparator(",", i);
- * append(list.get(i));
- * }
- *
- * Note that for this simple example, you should use
- * {@link #appendWithSeparators(Iterable, String)}.
- *
- * @param separator the separator to use, null means no separator
- * @param loopIndex the loop index
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendSeparator(final String separator, final int loopIndex) {
- if (separator != null && loopIndex > 0) {
- append(separator);
- }
- return this;
- }
-
- /**
- * Appends a separator to the builder if the loop index is greater than zero.
- * The separator is appended using {@link #append(char)}.
- *
- * This method is useful for adding a separator each time around the
- * loop except the first.
- *
- *
- * for (int i = 0; i < list.size(); i++) {
- * appendSeparator(",", i);
- * append(list.get(i));
- * }
- *
- * Note that for this simple example, you should use
- * {@link #appendWithSeparators(Iterable, String)}.
- *
- * @param separator the separator to use
- * @param loopIndex the loop index
- * @return this, to enable chaining
- * @since 2.3
- */
- public StrBuilder appendSeparator(final char separator, final int loopIndex) {
- if (loopIndex > 0) {
- append(separator);
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends the pad character to the builder the specified number of times.
- *
- * @param length the length to append, negative means no append
- * @param padChar the character to append
- * @return this, to enable chaining
- */
- public StrBuilder appendPadding(final int length, final char padChar) {
- if (length >= 0) {
- ensureCapacity(size + length);
- for (int i = 0; i < length; i++) {
- buffer[size++] = padChar;
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Appends an object to the builder padding on the left to a fixed width.
- * The toString of the object is used.
- * If the object is larger than the length, the left hand side is lost.
- * If the object is null, the null text value is used.
- *
- * @param obj the object to append, null uses null text
- * @param width the fixed field width, zero or negative has no effect
- * @param padChar the pad character to use
- * @return this, to enable chaining
- */
- public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) {
- if (width > 0) {
- ensureCapacity(size + width);
- String str = (obj == null ? getNullText() : obj.toString());
- if (str == null) {
- str = StringUtils.EMPTY;
- }
- final int strLen = str.length();
- if (strLen >= width) {
- str.getChars(strLen - width, strLen, buffer, size);
- } else {
- final int padLen = width - strLen;
- for (int i = 0; i < padLen; i++) {
- buffer[size + i] = padChar;
- }
- str.getChars(0, strLen, buffer, size + padLen);
- }
- size += width;
- }
- return this;
- }
-
- /**
- * Appends an object to the builder padding on the left to a fixed width.
- * The String.valueOf of the int value is used.
- * If the formatted value is larger than the length, the left hand side is lost.
- *
- * @param value the value to append
- * @param width the fixed field width, zero or negative has no effect
- * @param padChar the pad character to use
- * @return this, to enable chaining
- */
- public StrBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) {
- return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
- }
-
- /**
- * Appends an object to the builder padding on the right to a fixed length.
- * The toString of the object is used.
- * If the object is larger than the length, the right hand side is lost.
- * If the object is null, null text value is used.
- *
- * @param obj the object to append, null uses null text
- * @param width the fixed field width, zero or negative has no effect
- * @param padChar the pad character to use
- * @return this, to enable chaining
- */
- public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) {
- if (width > 0) {
- ensureCapacity(size + width);
- String str = (obj == null ? getNullText() : obj.toString());
- if (str == null) {
- str = StringUtils.EMPTY;
- }
- final int strLen = str.length();
- if (strLen >= width) {
- str.getChars(0, width, buffer, size);
- } else {
- final int padLen = width - strLen;
- str.getChars(0, strLen, buffer, size);
- for (int i = 0; i < padLen; i++) {
- buffer[size + strLen + i] = padChar;
- }
- }
- size += width;
- }
- return this;
- }
-
- /**
- * Appends an object to the builder padding on the right to a fixed length.
- * The String.valueOf of the int value is used.
- * If the object is larger than the length, the right hand side is lost.
- *
- * @param value the value to append
- * @param width the fixed field width, zero or negative has no effect
- * @param padChar the pad character to use
- * @return this, to enable chaining
- */
- public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) {
- return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Inserts the string representation of an object into this builder.
- * Inserting null will use the stored null text value.
- *
- * @param index the index to add at, must be valid
- * @param obj the object to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final Object obj) {
- if (obj == null) {
- return insert(index, nullText);
- }
- return insert(index, obj.toString());
- }
-
- /**
- * Inserts the string into this builder.
- * Inserting null will use the stored null text value.
- *
- * @param index the index to add at, must be valid
- * @param str the string to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, String str) {
- validateIndex(index);
- if (str == null) {
- str = nullText;
- }
- if (str != null) {
- final int strLen = str.length();
- if (strLen > 0) {
- final int newSize = size + strLen;
- ensureCapacity(newSize);
- System.arraycopy(buffer, index, buffer, index + strLen, size - index);
- size = newSize;
- str.getChars(0, strLen, buffer, index);
- }
- }
- return this;
- }
-
- /**
- * Inserts the character array into this builder.
- * Inserting null will use the stored null text value.
- *
- * @param index the index to add at, must be valid
- * @param chars the char array to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final char chars[]) {
- validateIndex(index);
- if (chars == null) {
- return insert(index, nullText);
- }
- final int len = chars.length;
- if (len > 0) {
- ensureCapacity(size + len);
- System.arraycopy(buffer, index, buffer, index + len, size - index);
- System.arraycopy(chars, 0, buffer, index, len);
- size += len;
- }
- return this;
- }
-
- /**
- * Inserts part of the character array into this builder.
- * Inserting null will use the stored null text value.
- *
- * @param index the index to add at, must be valid
- * @param chars the char array to insert
- * @param offset the offset into the character array to start at, must be valid
- * @param length the length of the character array part to copy, must be positive
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if any index is invalid
- */
- public StrBuilder insert(final int index, final char chars[], final int offset, final int length) {
- validateIndex(index);
- if (chars == null) {
- return insert(index, nullText);
- }
- if (offset < 0 || offset > chars.length) {
- throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
- }
- if (length < 0 || offset + length > chars.length) {
- throw new StringIndexOutOfBoundsException("Invalid length: " + length);
- }
- if (length > 0) {
- ensureCapacity(size + length);
- System.arraycopy(buffer, index, buffer, index + length, size - index);
- System.arraycopy(chars, offset, buffer, index, length);
- size += length;
- }
- return this;
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(int index, final boolean value) {
- validateIndex(index);
- if (value) {
- ensureCapacity(size + 4);
- System.arraycopy(buffer, index, buffer, index + 4, size - index);
- buffer[index++] = 't';
- buffer[index++] = 'r';
- buffer[index++] = 'u';
- buffer[index] = 'e';
- size += 4;
- } else {
- ensureCapacity(size + 5);
- System.arraycopy(buffer, index, buffer, index + 5, size - index);
- buffer[index++] = 'f';
- buffer[index++] = 'a';
- buffer[index++] = 'l';
- buffer[index++] = 's';
- buffer[index] = 'e';
- size += 5;
- }
- return this;
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final char value) {
- validateIndex(index);
- ensureCapacity(size + 1);
- System.arraycopy(buffer, index, buffer, index + 1, size - index);
- buffer[index] = value;
- size++;
- return this;
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final int value) {
- return insert(index, String.valueOf(value));
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final long value) {
- return insert(index, String.valueOf(value));
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final float value) {
- return insert(index, String.valueOf(value));
- }
-
- /**
- * Inserts the value into this builder.
- *
- * @param index the index to add at, must be valid
- * @param value the value to insert
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder insert(final int index, final double value) {
- return insert(index, String.valueOf(value));
- }
-
- //-----------------------------------------------------------------------
- /**
- * Internal method to delete a range without validation.
- *
- * @param startIndex the start index, must be valid
- * @param endIndex the end index (exclusive), must be valid
- * @param len the length, must be valid
- * @throws IndexOutOfBoundsException if any index is invalid
- */
- private void deleteImpl(final int startIndex, final int endIndex, final int len) {
- System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
- size -= len;
- }
-
- /**
- * Deletes the characters between the two specified indices.
- *
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except
- * that if too large it is treated as end of string
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder delete(final int startIndex, int endIndex) {
- endIndex = validateRange(startIndex, endIndex);
- final int len = endIndex - startIndex;
- if (len > 0) {
- deleteImpl(startIndex, endIndex, len);
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes the character wherever it occurs in the builder.
- *
- * @param ch the character to delete
- * @return this, to enable chaining
- */
- public StrBuilder deleteAll(final char ch) {
- for (int i = 0; i < size; i++) {
- if (buffer[i] == ch) {
- final int start = i;
- while (++i < size) {
- if (buffer[i] != ch) {
- break;
- }
- }
- final int len = i - start;
- deleteImpl(start, i, len);
- i -= len;
- }
- }
- return this;
- }
-
- /**
- * Deletes the character wherever it occurs in the builder.
- *
- * @param ch the character to delete
- * @return this, to enable chaining
- */
- public StrBuilder deleteFirst(final char ch) {
- for (int i = 0; i < size; i++) {
- if (buffer[i] == ch) {
- deleteImpl(i, i + 1, 1);
- break;
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes the string wherever it occurs in the builder.
- *
- * @param str the string to delete, null causes no action
- * @return this, to enable chaining
- */
- public StrBuilder deleteAll(final String str) {
- final int len = (str == null ? 0 : str.length());
- if (len > 0) {
- int index = indexOf(str, 0);
- while (index >= 0) {
- deleteImpl(index, index + len, len);
- index = indexOf(str, index);
- }
- }
- return this;
- }
-
- /**
- * Deletes the string wherever it occurs in the builder.
- *
- * @param str the string to delete, null causes no action
- * @return this, to enable chaining
- */
- public StrBuilder deleteFirst(final String str) {
- final int len = (str == null ? 0 : str.length());
- if (len > 0) {
- final int index = indexOf(str, 0);
- if (index >= 0) {
- deleteImpl(index, index + len, len);
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Deletes all parts of the builder that the matcher matches.
- *
- * Matchers can be used to perform advanced deletion behaviour.
- * For example you could write a matcher to delete all occurrences
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @return this, to enable chaining
- */
- public StrBuilder deleteAll(final StrMatcher matcher) {
- return replace(matcher, null, 0, size, -1);
- }
-
- /**
- * Deletes the first match within the builder using the specified matcher.
- *
- * Matchers can be used to perform advanced deletion behaviour.
- * For example you could write a matcher to delete
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @return this, to enable chaining
- */
- public StrBuilder deleteFirst(final StrMatcher matcher) {
- return replace(matcher, null, 0, size, 1);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Internal method to delete a range without validation.
- *
- * @param startIndex the start index, must be valid
- * @param endIndex the end index (exclusive), must be valid
- * @param removeLen the length to remove (endIndex - startIndex), must be valid
- * @param insertStr the string to replace with, null means delete range
- * @param insertLen the length of the insert string, must be valid
- * @throws IndexOutOfBoundsException if any index is invalid
- */
- private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, final int insertLen) {
- final int newSize = size - removeLen + insertLen;
- if (insertLen != removeLen) {
- ensureCapacity(newSize);
- System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
- size = newSize;
- }
- if (insertLen > 0) {
- insertStr.getChars(0, insertLen, buffer, startIndex);
- }
- }
-
- /**
- * Replaces a portion of the string builder with another string.
- * The length of the inserted string does not have to match the removed length.
- *
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except
- * that if too large it is treated as end of string
- * @param replaceStr the string to replace with, null means delete range
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) {
- endIndex = validateRange(startIndex, endIndex);
- final int insertLen = (replaceStr == null ? 0 : replaceStr.length());
- replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Replaces the search character with the replace character
- * throughout the builder.
- *
- * @param search the search character
- * @param replace the replace character
- * @return this, to enable chaining
- */
- public StrBuilder replaceAll(final char search, final char replace) {
- if (search != replace) {
- for (int i = 0; i < size; i++) {
- if (buffer[i] == search) {
- buffer[i] = replace;
- }
- }
- }
- return this;
- }
-
- /**
- * Replaces the first instance of the search character with the
- * replace character in the builder.
- *
- * @param search the search character
- * @param replace the replace character
- * @return this, to enable chaining
- */
- public StrBuilder replaceFirst(final char search, final char replace) {
- if (search != replace) {
- for (int i = 0; i < size; i++) {
- if (buffer[i] == search) {
- buffer[i] = replace;
- break;
- }
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Replaces the search string with the replace string throughout the builder.
- *
- * @param searchStr the search string, null causes no action to occur
- * @param replaceStr the replace string, null is equivalent to an empty string
- * @return this, to enable chaining
- */
- public StrBuilder replaceAll(final String searchStr, final String replaceStr) {
- final int searchLen = (searchStr == null ? 0 : searchStr.length());
- if (searchLen > 0) {
- final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
- int index = indexOf(searchStr, 0);
- while (index >= 0) {
- replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
- index = indexOf(searchStr, index + replaceLen);
- }
- }
- return this;
- }
-
- /**
- * Replaces the first instance of the search string with the replace string.
- *
- * @param searchStr the search string, null causes no action to occur
- * @param replaceStr the replace string, null is equivalent to an empty string
- * @return this, to enable chaining
- */
- public StrBuilder replaceFirst(final String searchStr, final String replaceStr) {
- final int searchLen = (searchStr == null ? 0 : searchStr.length());
- if (searchLen > 0) {
- final int index = indexOf(searchStr, 0);
- if (index >= 0) {
- final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
- replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Replaces all matches within the builder with the replace string.
- *
- * Matchers can be used to perform advanced replace behaviour.
- * For example you could write a matcher to replace all occurrences
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @param replaceStr the replace string, null is equivalent to an empty string
- * @return this, to enable chaining
- */
- public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) {
- return replace(matcher, replaceStr, 0, size, -1);
- }
-
- /**
- * Replaces the first match within the builder with the replace string.
- *
- * Matchers can be used to perform advanced replace behaviour.
- * For example you could write a matcher to replace
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @param replaceStr the replace string, null is equivalent to an empty string
- * @return this, to enable chaining
- */
- public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) {
- return replace(matcher, replaceStr, 0, size, 1);
- }
-
- // -----------------------------------------------------------------------
- /**
- * Advanced search and replaces within the builder using a matcher.
- *
- * Matchers can be used to perform advanced behaviour.
- * For example you could write a matcher to delete all occurrences
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @param replaceStr the string to replace the match with, null is a delete
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except
- * that if too large it is treated as end of string
- * @param replaceCount the number of times to replace, -1 for replace all
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if start index is invalid
- */
- public StrBuilder replace(
- final StrMatcher matcher, final String replaceStr,
- final int startIndex, int endIndex, final int replaceCount) {
- endIndex = validateRange(startIndex, endIndex);
- return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
- }
-
- /**
- * Replaces within the builder using a matcher.
- *
- * Matchers can be used to perform advanced behaviour.
- * For example you could write a matcher to delete all occurrences
- * where the character 'a' is followed by a number.
- *
- * @param matcher the matcher to use to find the deletion, null causes no action
- * @param replaceStr the string to replace the match with, null is a delete
- * @param from the start index, must be valid
- * @param to the end index (exclusive), must be valid
- * @param replaceCount the number of times to replace, -1 for replace all
- * @return this, to enable chaining
- * @throws IndexOutOfBoundsException if any index is invalid
- */
- private StrBuilder replaceImpl(
- final StrMatcher matcher, final String replaceStr,
- final int from, int to, int replaceCount) {
- if (matcher == null || size == 0) {
- return this;
- }
- final int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
- for (int i = from; i < to && replaceCount != 0; i++) {
- final char[] buf = buffer;
- final int removeLen = matcher.isMatch(buf, i, from, to);
- if (removeLen > 0) {
- replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
- to = to - removeLen + replaceLen;
- i = i + replaceLen - 1;
- if (replaceCount > 0) {
- replaceCount--;
- }
- }
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Reverses the string builder placing each character in the opposite index.
- *
- * @return this, to enable chaining
- */
- public StrBuilder reverse() {
- if (size == 0) {
- return this;
- }
-
- final int half = size / 2;
- final char[] buf = buffer;
- for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++,rightIdx--) {
- final char swap = buf[leftIdx];
- buf[leftIdx] = buf[rightIdx];
- buf[rightIdx] = swap;
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Trims the builder by removing characters less than or equal to a space
- * from the beginning and end.
- *
- * @return this, to enable chaining
- */
- public StrBuilder trim() {
- if (size == 0) {
- return this;
- }
- int len = size;
- final char[] buf = buffer;
- int pos = 0;
- while (pos < len && buf[pos] <= ' ') {
- pos++;
- }
- while (pos < len && buf[len - 1] <= ' ') {
- len--;
- }
- if (len < size) {
- delete(len, size);
- }
- if (pos > 0) {
- delete(0, pos);
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks whether this builder starts with the specified string.
- *
- * Note that this method handles null input quietly, unlike String.
- *
- * @param str the string to search for, null returns false
- * @return true if the builder starts with the string
- */
- public boolean startsWith(final String str) {
- if (str == null) {
- return false;
- }
- final int len = str.length();
- if (len == 0) {
- return true;
- }
- if (len > size) {
- return false;
- }
- for (int i = 0; i < len; i++) {
- if (buffer[i] != str.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks whether this builder ends with the specified string.
- *
- * Note that this method handles null input quietly, unlike String.
- *
- * @param str the string to search for, null returns false
- * @return true if the builder ends with the string
- */
- public boolean endsWith(final String str) {
- if (str == null) {
- return false;
- }
- final int len = str.length();
- if (len == 0) {
- return true;
- }
- if (len > size) {
- return false;
- }
- int pos = size - len;
- for (int i = 0; i < len; i++,pos++) {
- if (buffer[pos] != str.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- //-----------------------------------------------------------------------
- /**
- * {@inheritDoc}
- * @since 3.0
- */
- @Override
- public CharSequence subSequence(final int startIndex, final int endIndex) {
- if (startIndex < 0) {
- throw new StringIndexOutOfBoundsException(startIndex);
- }
- if (endIndex > size) {
- throw new StringIndexOutOfBoundsException(endIndex);
- }
- if (startIndex > endIndex) {
- throw new StringIndexOutOfBoundsException(endIndex - startIndex);
- }
- return substring(startIndex, endIndex);
- }
-
- /**
- * Extracts a portion of this string builder as a string.
- *
- * @param start the start index, inclusive, must be valid
- * @return the new string
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public String substring(final int start) {
- return substring(start, size);
- }
-
- /**
- * Extracts a portion of this string builder as a string.
- *
- * Note: This method treats an endIndex greater than the length of the
- * builder as equal to the length of the builder, and continues
- * without error, unlike StringBuffer or String.
- *
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except
- * that if too large it is treated as end of string
- * @return the new string
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- public String substring(final int startIndex, int endIndex) {
- endIndex = validateRange(startIndex, endIndex);
- return new String(buffer, startIndex, endIndex - startIndex);
- }
-
- /**
- * Extracts the leftmost characters from the string builder without
- * throwing an exception.
- *
- * This method extracts the left length characters from
- * the builder. If this many characters are not available, the whole
- * builder is returned. Thus the returned string may be shorter than the
- * length requested.
- *
- * @param length the number of characters to extract, negative returns empty string
- * @return the new string
- */
- public String leftString(final int length) {
- if (length <= 0) {
- return StringUtils.EMPTY;
- } else if (length >= size) {
- return new String(buffer, 0, size);
- } else {
- return new String(buffer, 0, length);
- }
- }
-
- /**
- * Extracts the rightmost characters from the string builder without
- * throwing an exception.
- *
- * This method extracts the right length characters from
- * the builder. If this many characters are not available, the whole
- * builder is returned. Thus the returned string may be shorter than the
- * length requested.
- *
- * @param length the number of characters to extract, negative returns empty string
- * @return the new string
- */
- public String rightString(final int length) {
- if (length <= 0) {
- return StringUtils.EMPTY;
- } else if (length >= size) {
- return new String(buffer, 0, size);
- } else {
- return new String(buffer, size - length, length);
- }
- }
-
- /**
- * Extracts some characters from the middle of the string builder without
- * throwing an exception.
- *
- * This method extracts length characters from the builder
- * at the specified index.
- * If the index is negative it is treated as zero.
- * If the index is greater than the builder size, it is treated as the builder size.
- * If the length is negative, the empty string is returned.
- * If insufficient characters are available in the builder, as much as possible is returned.
- * Thus the returned string may be shorter than the length requested.
- *
- * @param index the index to start at, negative means zero
- * @param length the number of characters to extract, negative returns empty string
- * @return the new string
- */
- public String midString(int index, final int length) {
- if (index < 0) {
- index = 0;
- }
- if (length <= 0 || index >= size) {
- return StringUtils.EMPTY;
- }
- if (size <= index + length) {
- return new String(buffer, index, size - index);
- }
- return new String(buffer, index, length);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Checks if the string builder contains the specified char.
- *
- * @param ch the character to find
- * @return true if the builder contains the character
- */
- public boolean contains(final char ch) {
- final char[] thisBuf = buffer;
- for (int i = 0; i < this.size; i++) {
- if (thisBuf[i] == ch) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if the string builder contains the specified string.
- *
- * @param str the string to find
- * @return true if the builder contains the string
- */
- public boolean contains(final String str) {
- return indexOf(str, 0) >= 0;
- }
-
- /**
- * Checks if the string builder contains a string matched using the
- * specified matcher.
- *
- * Matchers can be used to perform advanced searching behaviour.
- * For example you could write a matcher to search for the character
- * 'a' followed by a number.
- *
- * @param matcher the matcher to use, null returns -1
- * @return true if the matcher finds a match in the builder
- */
- public boolean contains(final StrMatcher matcher) {
- return indexOf(matcher, 0) >= 0;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Searches the string builder to find the first reference to the specified char.
- *
- * @param ch the character to find
- * @return the first index of the character, or -1 if not found
- */
- public int indexOf(final char ch) {
- return indexOf(ch, 0);
- }
-
- /**
- * Searches the string builder to find the first reference to the specified char.
- *
- * @param ch the character to find
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the first index of the character, or -1 if not found
- */
- public int indexOf(final char ch, int startIndex) {
- startIndex = (startIndex < 0 ? 0 : startIndex);
- if (startIndex >= size) {
- return -1;
- }
- final char[] thisBuf = buffer;
- for (int i = startIndex; i < size; i++) {
- if (thisBuf[i] == ch) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Searches the string builder to find the first reference to the specified string.
- *
- * Note that a null input string will return -1, whereas the JDK throws an exception.
- *
- * @param str the string to find, null returns -1
- * @return the first index of the string, or -1 if not found
- */
- public int indexOf(final String str) {
- return indexOf(str, 0);
- }
-
- /**
- * Searches the string builder to find the first reference to the specified
- * string starting searching from the given index.
- *
- * Note that a null input string will return -1, whereas the JDK throws an exception.
- *
- * @param str the string to find, null returns -1
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the first index of the string, or -1 if not found
- */
- public int indexOf(final String str, int startIndex) {
- startIndex = (startIndex < 0 ? 0 : startIndex);
- if (str == null || startIndex >= size) {
- return -1;
- }
- final int strLen = str.length();
- if (strLen == 1) {
- return indexOf(str.charAt(0), startIndex);
- }
- if (strLen == 0) {
- return startIndex;
- }
- if (strLen > size) {
- return -1;
- }
- final char[] thisBuf = buffer;
- final int len = size - strLen + 1;
- outer:
- for (int i = startIndex; i < len; i++) {
- for (int j = 0; j < strLen; j++) {
- if (str.charAt(j) != thisBuf[i + j]) {
- continue outer;
- }
- }
- return i;
- }
- return -1;
- }
-
- /**
- * Searches the string builder using the matcher to find the first match.
- *
- * Matchers can be used to perform advanced searching behaviour.
- * For example you could write a matcher to find the character 'a'
- * followed by a number.
- *
- * @param matcher the matcher to use, null returns -1
- * @return the first index matched, or -1 if not found
- */
- public int indexOf(final StrMatcher matcher) {
- return indexOf(matcher, 0);
- }
-
- /**
- * Searches the string builder using the matcher to find the first
- * match searching from the given index.
- *
- * Matchers can be used to perform advanced searching behaviour.
- * For example you could write a matcher to find the character 'a'
- * followed by a number.
- *
- * @param matcher the matcher to use, null returns -1
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the first index matched, or -1 if not found
- */
- public int indexOf(final StrMatcher matcher, int startIndex) {
- startIndex = (startIndex < 0 ? 0 : startIndex);
- if (matcher == null || startIndex >= size) {
- return -1;
- }
- final int len = size;
- final char[] buf = buffer;
- for (int i = startIndex; i < len; i++) {
- if (matcher.isMatch(buf, i, startIndex, len) > 0) {
- return i;
- }
- }
- return -1;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Searches the string builder to find the last reference to the specified char.
- *
- * @param ch the character to find
- * @return the last index of the character, or -1 if not found
- */
- public int lastIndexOf(final char ch) {
- return lastIndexOf(ch, size - 1);
- }
-
- /**
- * Searches the string builder to find the last reference to the specified char.
- *
- * @param ch the character to find
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the last index of the character, or -1 if not found
- */
- public int lastIndexOf(final char ch, int startIndex) {
- startIndex = (startIndex >= size ? size - 1 : startIndex);
- if (startIndex < 0) {
- return -1;
- }
- for (int i = startIndex; i >= 0; i--) {
- if (buffer[i] == ch) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Searches the string builder to find the last reference to the specified string.
- *
- * Note that a null input string will return -1, whereas the JDK throws an exception.
- *
- * @param str the string to find, null returns -1
- * @return the last index of the string, or -1 if not found
- */
- public int lastIndexOf(final String str) {
- return lastIndexOf(str, size - 1);
- }
-
- /**
- * Searches the string builder to find the last reference to the specified
- * string starting searching from the given index.
- *
- * Note that a null input string will return -1, whereas the JDK throws an exception.
- *
- * @param str the string to find, null returns -1
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the last index of the string, or -1 if not found
- */
- public int lastIndexOf(final String str, int startIndex) {
- startIndex = (startIndex >= size ? size - 1 : startIndex);
- if (str == null || startIndex < 0) {
- return -1;
- }
- final int strLen = str.length();
- if (strLen > 0 && strLen <= size) {
- if (strLen == 1) {
- return lastIndexOf(str.charAt(0), startIndex);
- }
-
- outer:
- for (int i = startIndex - strLen + 1; i >= 0; i--) {
- for (int j = 0; j < strLen; j++) {
- if (str.charAt(j) != buffer[i + j]) {
- continue outer;
- }
- }
- return i;
- }
-
- } else if (strLen == 0) {
- return startIndex;
- }
- return -1;
- }
-
- /**
- * Searches the string builder using the matcher to find the last match.
- *
- * Matchers can be used to perform advanced searching behaviour.
- * For example you could write a matcher to find the character 'a'
- * followed by a number.
- *
- * @param matcher the matcher to use, null returns -1
- * @return the last index matched, or -1 if not found
- */
- public int lastIndexOf(final StrMatcher matcher) {
- return lastIndexOf(matcher, size);
- }
-
- /**
- * Searches the string builder using the matcher to find the last
- * match searching from the given index.
- *
- * Matchers can be used to perform advanced searching behaviour.
- * For example you could write a matcher to find the character 'a'
- * followed by a number.
- *
- * @param matcher the matcher to use, null returns -1
- * @param startIndex the index to start at, invalid index rounded to edge
- * @return the last index matched, or -1 if not found
- */
- public int lastIndexOf(final StrMatcher matcher, int startIndex) {
- startIndex = (startIndex >= size ? size - 1 : startIndex);
- if (matcher == null || startIndex < 0) {
- return -1;
- }
- final char[] buf = buffer;
- final int endIndex = startIndex + 1;
- for (int i = startIndex; i >= 0; i--) {
- if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
- return i;
- }
- }
- return -1;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Creates a tokenizer that can tokenize the contents of this builder.
- *
- * This method allows the contents of this builder to be tokenized.
- * The tokenizer will be setup by default to tokenize on space, tab,
- * newline and formfeed (as per StringTokenizer). These values can be
- * changed on the tokenizer class, before retrieving the tokens.
- *
- * The returned tokenizer is linked to this builder. You may intermix
- * calls to the builder and tokenizer within certain limits, however
- * there is no synchronization. Once the tokenizer has been used once,
- * it must be {@link StrTokenizer#reset() reset} to pickup the latest
- * changes in the builder. For example:
- *
- * StrBuilder b = new StrBuilder();
- * b.append("a b ");
- * StrTokenizer t = b.asTokenizer();
- * String[] tokens1 = t.getTokenArray(); // returns a,b
- * b.append("c d ");
- * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
- * t.reset(); // reset causes builder changes to be picked up
- * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
- *
- * In addition to simply intermixing appends and tokenization, you can also
- * call the set methods on the tokenizer to alter how it tokenizes. Just
- * remember to call reset when you want to pickup builder changes.
- *
- * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])}
- * with a non-null value will break the link with the builder.
- *
- * @return a tokenizer that is linked to this builder
- */
- public StrTokenizer asTokenizer() {
- return new StrBuilderTokenizer();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the contents of this builder as a Reader.
- *
- * This method allows the contents of the builder to be read
- * using any standard method that expects a Reader.
- *
- * To use, simply create a StrBuilder, populate it with
- * data, call asReader, and then read away.
- *
- * The internal character array is shared between the builder and the reader.
- * This allows you to append to the builder after creating the reader,
- * and the changes will be picked up.
- * Note however, that no synchronization occurs, so you must perform
- * all operations with the builder and the reader in one thread.
- *
- * The returned reader supports marking, and ignores the flush method.
- *
- * @return a reader that reads from this builder
- */
- public Reader asReader() {
- return new StrBuilderReader();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets this builder as a Writer that can be written to.
- *
- * This method allows you to populate the contents of the builder
- * using any standard method that takes a Writer.
- *
- * To use, simply create a StrBuilder,
- * call asWriter, and populate away. The data is available
- * at any time using the methods of the StrBuilder.
- *
- * The internal character array is shared between the builder and the writer.
- * This allows you to intermix calls that append to the builder and
- * write using the writer and the changes will be occur correctly.
- * Note however, that no synchronization occurs, so you must perform
- * all operations with the builder and the writer in one thread.
- *
- * The returned writer ignores the close and flush methods.
- *
- * @return a writer that populates this builder
- */
- public Writer asWriter() {
- return new StrBuilderWriter();
- }
-
- /**
- * Appends current contents of this StrBuilder to the
- * provided {@link Appendable}.
- *
- * This method tries to avoid doing any extra copies of contents.
- *
- * @param appendable the appendable to append data to
- * @throws IOException if an I/O error occurs
- *
- * @since 3.4
- * @see #readFrom(Readable)
- */
- public void appendTo(final Appendable appendable) throws IOException {
- if (appendable instanceof Writer) {
- ((Writer) appendable).write(buffer, 0, size);
- } else if (appendable instanceof StringBuilder) {
- ((StringBuilder) appendable).append(buffer, 0, size);
- } else if (appendable instanceof StringBuffer) {
- ((StringBuffer) appendable).append(buffer, 0, size);
- } else if (appendable instanceof CharBuffer) {
- ((CharBuffer) appendable).put(buffer, 0, size);
- } else {
- appendable.append(this);
- }
- }
-
- /**
- * Checks the contents of this builder against another to see if they
- * contain the same character content ignoring case.
- *
- * @param other the object to check, null returns false
- * @return true if the builders contain the same characters in the same order
- */
- public boolean equalsIgnoreCase(final StrBuilder other) {
- if (this == other) {
- return true;
- }
- if (this.size != other.size) {
- return false;
- }
- final char thisBuf[] = this.buffer;
- final char otherBuf[] = other.buffer;
- for (int i = size - 1; i >= 0; i--) {
- final char c1 = thisBuf[i];
- final char c2 = otherBuf[i];
- if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks the contents of this builder against another to see if they
- * contain the same character content.
- *
- * @param other the object to check, null returns false
- * @return true if the builders contain the same characters in the same order
- */
- public boolean equals(final StrBuilder other) {
- if (this == other) {
- return true;
- }
- if (other == null) {
- return false;
- }
- if (this.size != other.size) {
- return false;
- }
- final char thisBuf[] = this.buffer;
- final char otherBuf[] = other.buffer;
- for (int i = size - 1; i >= 0; i--) {
- if (thisBuf[i] != otherBuf[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks the contents of this builder against another to see if they
- * contain the same character content.
- *
- * @param obj the object to check, null returns false
- * @return true if the builders contain the same characters in the same order
- */
- @Override
- public boolean equals(final Object obj) {
- return obj instanceof StrBuilder && equals((StrBuilder) obj);
- }
-
- /**
- * Gets a suitable hash code for this builder.
- *
- * @return a hash code
- */
- @Override
- public int hashCode() {
- final char buf[] = buffer;
- int hash = 0;
- for (int i = size - 1; i >= 0; i--) {
- hash = 31 * hash + buf[i];
- }
- return hash;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets a String version of the string builder, creating a new instance
- * each time the method is called.
- *
- * Note that unlike StringBuffer, the string version returned is
- * independent of the string builder.
- *
- * @return the builder as a String
- */
- @Override
- public String toString() {
- return new String(buffer, 0, size);
- }
-
- /**
- * Gets a StringBuffer version of the string builder, creating a
- * new instance each time the method is called.
- *
- * @return the builder as a StringBuffer
- */
- public StringBuffer toStringBuffer() {
- return new StringBuffer(size).append(buffer, 0, size);
- }
-
- /**
- * Gets a StringBuilder version of the string builder, creating a
- * new instance each time the method is called.
- *
- * @return the builder as a StringBuilder
- * @since 3.2
- */
- public StringBuilder toStringBuilder() {
- return new StringBuilder(size).append(buffer, 0, size);
- }
-
- /**
- * Implement the {@link Builder} interface.
- * @return the builder as a String
- * @since 3.2
- * @see #toString()
- */
- @Override
- public String build() {
- return toString();
- }
-
- //-----------------------------------------------------------------------
- /**
- * Validates parameters defining a range of the builder.
- *
- * @param startIndex the start index, inclusive, must be valid
- * @param endIndex the end index, exclusive, must be valid except
- * that if too large it is treated as end of string
- * @return the new string
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- protected int validateRange(final int startIndex, int endIndex) {
- if (startIndex < 0) {
- throw new StringIndexOutOfBoundsException(startIndex);
- }
- if (endIndex > size) {
- endIndex = size;
- }
- if (startIndex > endIndex) {
- throw new StringIndexOutOfBoundsException("end < start");
- }
- return endIndex;
- }
-
- /**
- * Validates parameters defining a single index in the builder.
- *
- * @param index the index, must be valid
- * @throws IndexOutOfBoundsException if the index is invalid
- */
- protected void validateIndex(final int index) {
- if (index < 0 || index > size) {
- throw new StringIndexOutOfBoundsException(index);
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Inner class to allow StrBuilder to operate as a tokenizer.
- */
- class StrBuilderTokenizer extends StrTokenizer {
-
- /**
- * Default constructor.
- */
- StrBuilderTokenizer() {
- super();
- }
-
- /** {@inheritDoc} */
- @Override
- protected List tokenize(final char[] chars, final int offset, final int count) {
- if (chars == null) {
- return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size());
- }
- return super.tokenize(chars, offset, count);
- }
-
- /** {@inheritDoc} */
- @Override
- public String getContent() {
- final String str = super.getContent();
- if (str == null) {
- return StrBuilder.this.toString();
- }
- return str;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Inner class to allow StrBuilder to operate as a reader.
- */
- class StrBuilderReader extends Reader {
- /** The current stream position. */
- private int pos;
- /** The last mark position. */
- private int mark;
-
- /**
- * Default constructor.
- */
- StrBuilderReader() {
- super();
- }
-
- /** {@inheritDoc} */
- @Override
- public void close() {
- // do nothing
- }
-
- /** {@inheritDoc} */
- @Override
- public int read() {
- if (ready() == false) {
- return -1;
- }
- return StrBuilder.this.charAt(pos++);
- }
-
- /** {@inheritDoc} */
- @Override
- public int read(final char b[], final int off, int len) {
- if (off < 0 || len < 0 || off > b.length ||
- (off + len) > b.length || (off + len) < 0) {
- throw new IndexOutOfBoundsException();
- }
- if (len == 0) {
- return 0;
- }
- if (pos >= StrBuilder.this.size()) {
- return -1;
- }
- if (pos + len > size()) {
- len = StrBuilder.this.size() - pos;
- }
- StrBuilder.this.getChars(pos, pos + len, b, off);
- pos += len;
- return len;
- }
-
- /** {@inheritDoc} */
- @Override
- public long skip(long n) {
- if (pos + n > StrBuilder.this.size()) {
- n = StrBuilder.this.size() - pos;
- }
- if (n < 0) {
- return 0;
- }
- pos += n;
- return n;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean ready() {
- return pos < StrBuilder.this.size();
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean markSupported() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- public void mark(final int readAheadLimit) {
- mark = pos;
- }
-
- /** {@inheritDoc} */
- @Override
- public void reset() {
- pos = mark;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Inner class to allow StrBuilder to operate as a writer.
- */
- class StrBuilderWriter extends Writer {
-
- /**
- * Default constructor.
- */
- StrBuilderWriter() {
- super();
- }
-
- /** {@inheritDoc} */
- @Override
- public void close() {
- // do nothing
- }
-
- /** {@inheritDoc} */
- @Override
- public void flush() {
- // do nothing
- }
-
- /** {@inheritDoc} */
- @Override
- public void write(final int c) {
- StrBuilder.this.append((char) c);
- }
-
- /** {@inheritDoc} */
- @Override
- public void write(final char[] cbuf) {
- StrBuilder.this.append(cbuf);
- }
-
- /** {@inheritDoc} */
- @Override
- public void write(final char[] cbuf, final int off, final int len) {
- StrBuilder.this.append(cbuf, off, len);
- }
-
- /** {@inheritDoc} */
- @Override
- public void write(final String str) {
- StrBuilder.this.append(str);
- }
-
- /** {@inheritDoc} */
- @Override
- public void write(final String str, final int off, final int len) {
- StrBuilder.this.append(str, off, len);
- }
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrMatcher.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrMatcher.java
deleted file mode 100644
index 353f8303..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrMatcher.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-import java.util.Arrays;
-
-/**
- * A matcher class that can be queried to determine if a character array
- * portion matches.
- *
- * This class comes complete with various factory methods.
- * If these do not suffice, you can subclass and implement your own matcher.
- *
- * @since 2.2
- * @deprecated as of 3.6, use commons-text
- *
- * StringMatcherFactory instead
- */
-@Deprecated
-public abstract class StrMatcher {
-
- /**
- * Matches the comma character.
- */
- private static final StrMatcher COMMA_MATCHER = new CharMatcher(',');
- /**
- * Matches the tab character.
- */
- private static final StrMatcher TAB_MATCHER = new CharMatcher('\t');
- /**
- * Matches the space character.
- */
- private static final StrMatcher SPACE_MATCHER = new CharMatcher(' ');
- /**
- * Matches the same characters as StringTokenizer,
- * namely space, tab, newline, formfeed.
- */
- private static final StrMatcher SPLIT_MATCHER = new CharSetMatcher(" \t\n\r\f".toCharArray());
- /**
- * Matches the String trim() whitespace characters.
- */
- private static final StrMatcher TRIM_MATCHER = new TrimMatcher();
- /**
- * Matches the double quote character.
- */
- private static final StrMatcher SINGLE_QUOTE_MATCHER = new CharMatcher('\'');
- /**
- * Matches the double quote character.
- */
- private static final StrMatcher DOUBLE_QUOTE_MATCHER = new CharMatcher('"');
- /**
- * Matches the single or double quote character.
- */
- private static final StrMatcher QUOTE_MATCHER = new CharSetMatcher("'\"".toCharArray());
- /**
- * Matches no characters.
- */
- private static final StrMatcher NONE_MATCHER = new NoMatcher();
-
- // -----------------------------------------------------------------------
-
- /**
- * Returns a matcher which matches the comma character.
- *
- * @return a matcher for a comma
- */
- public static StrMatcher commaMatcher() {
- return COMMA_MATCHER;
- }
-
- /**
- * Returns a matcher which matches the tab character.
- *
- * @return a matcher for a tab
- */
- public static StrMatcher tabMatcher() {
- return TAB_MATCHER;
- }
-
- /**
- * Returns a matcher which matches the space character.
- *
- * @return a matcher for a space
- */
- public static StrMatcher spaceMatcher() {
- return SPACE_MATCHER;
- }
-
- /**
- * Matches the same characters as StringTokenizer,
- * namely space, tab, newline and formfeed.
- *
- * @return the split matcher
- */
- public static StrMatcher splitMatcher() {
- return SPLIT_MATCHER;
- }
-
- /**
- * Matches the String trim() whitespace characters.
- *
- * @return the trim matcher
- */
- public static StrMatcher trimMatcher() {
- return TRIM_MATCHER;
- }
-
- /**
- * Returns a matcher which matches the single quote character.
- *
- * @return a matcher for a single quote
- */
- public static StrMatcher singleQuoteMatcher() {
- return SINGLE_QUOTE_MATCHER;
- }
-
- /**
- * Returns a matcher which matches the double quote character.
- *
- * @return a matcher for a double quote
- */
- public static StrMatcher doubleQuoteMatcher() {
- return DOUBLE_QUOTE_MATCHER;
- }
-
- /**
- * Returns a matcher which matches the single or double quote character.
- *
- * @return a matcher for a single or double quote
- */
- public static StrMatcher quoteMatcher() {
- return QUOTE_MATCHER;
- }
-
- /**
- * Matches no characters.
- *
- * @return a matcher that matches nothing
- */
- public static StrMatcher noneMatcher() {
- return NONE_MATCHER;
- }
-
- /**
- * Constructor that creates a matcher from a character.
- *
- * @param ch the character to match, must not be null
- * @return a new Matcher for the given char
- */
- public static StrMatcher charMatcher(final char ch) {
- return new CharMatcher(ch);
- }
-
- /**
- * Constructor that creates a matcher from a set of characters.
- *
- * @param chars the characters to match, null or empty matches nothing
- * @return a new matcher for the given char[]
- */
- public static StrMatcher charSetMatcher(final char... chars) {
- if (chars == null || chars.length == 0) {
- return NONE_MATCHER;
- }
- if (chars.length == 1) {
- return new CharMatcher(chars[0]);
- }
- return new CharSetMatcher(chars);
- }
-
- /**
- * Constructor that creates a matcher from a string representing a set of characters.
- *
- * @param chars the characters to match, null or empty matches nothing
- * @return a new Matcher for the given characters
- */
- public static StrMatcher charSetMatcher(final String chars) {
- if (StringUtils.isEmpty(chars)) {
- return NONE_MATCHER;
- }
- if (chars.length() == 1) {
- return new CharMatcher(chars.charAt(0));
- }
- return new CharSetMatcher(chars.toCharArray());
- }
-
- /**
- * Constructor that creates a matcher from a string.
- *
- * @param str the string to match, null or empty matches nothing
- * @return a new Matcher for the given String
- */
- public static StrMatcher stringMatcher(final String str) {
- if (StringUtils.isEmpty(str)) {
- return NONE_MATCHER;
- }
- return new StringMatcher(str);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Constructor.
- */
- protected StrMatcher() {
- super();
- }
-
- /**
- * Returns the number of matching characters, zero for no match.
- *
- * This method is called to check for a match.
- * The parameter pos represents the current position to be
- * checked in the string buffer (a character array which must
- * not be changed).
- * The API guarantees that pos is a valid index for buffer.
- *
- * The character array may be larger than the active area to be matched.
- * Only values in the buffer between the specified indices may be accessed.
- *
- * The matching code may check one character or many.
- * It may check characters preceding pos as well as those
- * after, so long as no checks exceed the bounds specified.
- *
- * It must return zero for no match, or a positive number if a match was found.
- * The number indicates the number of characters that matched.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index (exclusive) of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- public abstract int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd);
-
- /**
- * Returns the number of matching characters, zero for no match.
- *
- * This method is called to check for a match.
- * The parameter pos represents the current position to be
- * checked in the string buffer (a character array which must
- * not be changed).
- * The API guarantees that pos is a valid index for buffer.
- *
- * The matching code may check one character or many.
- * It may check characters preceding pos as well as those after.
- *
- * It must return zero for no match, or a positive number if a match was found.
- * The number indicates the number of characters that matched.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @return the number of matching characters, zero for no match
- * @since 2.4
- */
- public int isMatch(final char[] buffer, final int pos) {
- return isMatch(buffer, pos, 0, buffer.length);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Class used to define a set of characters for matching purposes.
- */
- static final class CharSetMatcher extends StrMatcher {
- /** The set of characters to match. */
- private final char[] chars;
-
- /**
- * Constructor that creates a matcher from a character array.
- *
- * @param chars the characters to match, must not be null
- */
- CharSetMatcher(final char chars[]) {
- super();
- this.chars = chars.clone();
- Arrays.sort(this.chars);
- }
-
- /**
- * Returns whether or not the given character matches.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- @Override
- public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) {
- return Arrays.binarySearch(chars, buffer[pos]) >= 0 ? 1 : 0;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Class used to define a character for matching purposes.
- */
- static final class CharMatcher extends StrMatcher {
- /** The character to match. */
- private final char ch;
-
- /**
- * Constructor that creates a matcher that matches a single character.
- *
- * @param ch the character to match
- */
- CharMatcher(final char ch) {
- super();
- this.ch = ch;
- }
-
- /**
- * Returns whether or not the given character matches.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- @Override
- public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) {
- return ch == buffer[pos] ? 1 : 0;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Class used to define a set of characters for matching purposes.
- */
- static final class StringMatcher extends StrMatcher {
- /** The string to match, as a character array. */
- private final char[] chars;
-
- /**
- * Constructor that creates a matcher from a String.
- *
- * @param str the string to match, must not be null
- */
- StringMatcher(final String str) {
- super();
- chars = str.toCharArray();
- }
-
- /**
- * Returns whether or not the given text matches the stored string.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- @Override
- public int isMatch(final char[] buffer, int pos, final int bufferStart, final int bufferEnd) {
- final int len = chars.length;
- if (pos + len > bufferEnd) {
- return 0;
- }
- for (int i = 0; i < chars.length; i++, pos++) {
- if (chars[i] != buffer[pos]) {
- return 0;
- }
- }
- return len;
- }
-
- @Override
- public String toString() {
- return super.toString() + ' ' + Arrays.toString(chars);
- }
-
- }
-
- //-----------------------------------------------------------------------
- /**
- * Class used to match no characters.
- */
- static final class NoMatcher extends StrMatcher {
-
- /**
- * Constructs a new instance of NoMatcher.
- */
- NoMatcher() {
- super();
- }
-
- /**
- * Always returns false.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- @Override
- public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) {
- return 0;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * Class used to match whitespace as per trim().
- */
- static final class TrimMatcher extends StrMatcher {
-
- /**
- * Constructs a new instance of TrimMatcher.
- */
- TrimMatcher() {
- super();
- }
-
- /**
- * Returns whether or not the given character matches.
- *
- * @param buffer the text content to match against, do not change
- * @param pos the starting position for the match, valid for buffer
- * @param bufferStart the first active index in the buffer, valid for buffer
- * @param bufferEnd the end index of the active buffer, valid for buffer
- * @return the number of matching characters, zero for no match
- */
- @Override
- public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) {
- return buffer[pos] <= 32 ? 1 : 0;
- }
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrTokenizer.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrTokenizer.java
deleted file mode 100644
index 42058be9..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StrTokenizer.java
+++ /dev/null
@@ -1,1112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-/**
- * Tokenizes a string based on delimiters (separators)
- * and supporting quoting and ignored character concepts.
- *
- * This class can split a String into many smaller strings. It aims
- * to do a similar job to {@link java.util.StringTokenizer StringTokenizer},
- * however it offers much more control and flexibility including implementing
- * the ListIterator interface. By default, it is set up
- * like StringTokenizer.
- *
- * The input String is split into a number of tokens .
- * Each token is separated from the next String by a delimiter .
- * One or more delimiter characters must be specified.
- *
- * Each token may be surrounded by quotes.
- * The quote matcher specifies the quote character(s).
- * A quote may be escaped within a quoted section by duplicating itself.
- *
- * Between each token and the delimiter are potentially characters that need trimming.
- * The trimmer matcher specifies these characters.
- * One usage might be to trim whitespace characters.
- *
- * At any point outside the quotes there might potentially be invalid characters.
- * The ignored matcher specifies these characters to be removed.
- * One usage might be to remove new line characters.
- *
- * Empty tokens may be removed or returned as null.
- *
- * "a,b,c" - Three tokens "a","b","c" (comma delimiter)
- * " a, b , c " - Three tokens "a","b","c" (default CSV processing trims whitespace)
- * "a, ", b ,", c" - Three tokens "a, " , " b ", ", c" (quoted text untouched)
- *
- *
- *
- * StrTokenizer properties and options
- *
- * Property Type Default
- *
- *
- * delim CharSetMatcher { \t\n\r\f}
- *
- *
- * quote NoneMatcher {}
- *
- *
- * ignore NoneMatcher {}
- *
- *
- * emptyTokenAsNull boolean false
- *
- *
- * ignoreEmptyTokens boolean true
- *
- *
- *
- * @since 2.2
- * @deprecated as of 3.6, use commons-text
- *
- * StringTokenizer instead
- */
-@Deprecated
-public class StrTokenizer implements ListIterator, Cloneable {
-
- private static final StrTokenizer CSV_TOKENIZER_PROTOTYPE;
- private static final StrTokenizer TSV_TOKENIZER_PROTOTYPE;
- static {
- CSV_TOKENIZER_PROTOTYPE = new StrTokenizer();
- CSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.commaMatcher());
- CSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher());
- CSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher());
- CSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher());
- CSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false);
- CSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false);
-
- TSV_TOKENIZER_PROTOTYPE = new StrTokenizer();
- TSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.tabMatcher());
- TSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher());
- TSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher());
- TSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher());
- TSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false);
- TSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false);
- }
-
- /** The text to work on. */
- private char chars[];
- /** The parsed tokens */
- private String tokens[];
- /** The current iteration position */
- private int tokenPos;
-
- /** The delimiter matcher */
- private StrMatcher delimMatcher = StrMatcher.splitMatcher();
- /** The quote matcher */
- private StrMatcher quoteMatcher = StrMatcher.noneMatcher();
- /** The ignored matcher */
- private StrMatcher ignoredMatcher = StrMatcher.noneMatcher();
- /** The trimmer matcher */
- private StrMatcher trimmerMatcher = StrMatcher.noneMatcher();
-
- /** Whether to return empty tokens as null */
- private boolean emptyAsNull = false;
- /** Whether to ignore empty tokens */
- private boolean ignoreEmptyTokens = true;
-
- //-----------------------------------------------------------------------
-
- /**
- * Returns a clone of CSV_TOKENIZER_PROTOTYPE.
- *
- * @return a clone of CSV_TOKENIZER_PROTOTYPE.
- */
- private static StrTokenizer getCSVClone() {
- return (StrTokenizer) CSV_TOKENIZER_PROTOTYPE.clone();
- }
-
- /**
- * Gets a new tokenizer instance which parses Comma Separated Value strings
- * initializing it with the given input. The default for CSV processing
- * will be trim whitespace from both ends (which can be overridden with
- * the setTrimmer method).
- *
- * You must call a "reset" method to set the string which you want to parse.
- * @return a new tokenizer instance which parses Comma Separated Value strings
- */
- public static StrTokenizer getCSVInstance() {
- return getCSVClone();
- }
-
- /**
- * Gets a new tokenizer instance which parses Comma Separated Value strings
- * initializing it with the given input. The default for CSV processing
- * will be trim whitespace from both ends (which can be overridden with
- * the setTrimmer method).
- *
- * @param input the text to parse
- * @return a new tokenizer instance which parses Comma Separated Value strings
- */
- public static StrTokenizer getCSVInstance(final String input) {
- final StrTokenizer tok = getCSVClone();
- tok.reset(input);
- return tok;
- }
-
- /**
- * Gets a new tokenizer instance which parses Comma Separated Value strings
- * initializing it with the given input. The default for CSV processing
- * will be trim whitespace from both ends (which can be overridden with
- * the setTrimmer method).
- *
- * @param input the text to parse
- * @return a new tokenizer instance which parses Comma Separated Value strings
- */
- public static StrTokenizer getCSVInstance(final char[] input) {
- final StrTokenizer tok = getCSVClone();
- tok.reset(input);
- return tok;
- }
-
- /**
- * Returns a clone of TSV_TOKENIZER_PROTOTYPE.
- *
- * @return a clone of TSV_TOKENIZER_PROTOTYPE.
- */
- private static StrTokenizer getTSVClone() {
- return (StrTokenizer) TSV_TOKENIZER_PROTOTYPE.clone();
- }
-
-
- /**
- * Gets a new tokenizer instance which parses Tab Separated Value strings.
- * The default for CSV processing will be trim whitespace from both ends
- * (which can be overridden with the setTrimmer method).
- *
- * You must call a "reset" method to set the string which you want to parse.
- * @return a new tokenizer instance which parses Tab Separated Value strings.
- */
- public static StrTokenizer getTSVInstance() {
- return getTSVClone();
- }
-
- /**
- * Gets a new tokenizer instance which parses Tab Separated Value strings.
- * The default for CSV processing will be trim whitespace from both ends
- * (which can be overridden with the setTrimmer method).
- * @param input the string to parse
- * @return a new tokenizer instance which parses Tab Separated Value strings.
- */
- public static StrTokenizer getTSVInstance(final String input) {
- final StrTokenizer tok = getTSVClone();
- tok.reset(input);
- return tok;
- }
-
- /**
- * Gets a new tokenizer instance which parses Tab Separated Value strings.
- * The default for CSV processing will be trim whitespace from both ends
- * (which can be overridden with the setTrimmer method).
- * @param input the string to parse
- * @return a new tokenizer instance which parses Tab Separated Value strings.
- */
- public static StrTokenizer getTSVInstance(final char[] input) {
- final StrTokenizer tok = getTSVClone();
- tok.reset(input);
- return tok;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Constructs a tokenizer splitting on space, tab, newline and formfeed
- * as per StringTokenizer, but with no text to tokenize.
- *
- * This constructor is normally used with {@link #reset(String)}.
- */
- public StrTokenizer() {
- super();
- this.chars = null;
- }
-
- /**
- * Constructs a tokenizer splitting on space, tab, newline and formfeed
- * as per StringTokenizer.
- *
- * @param input the string which is to be parsed
- */
- public StrTokenizer(final String input) {
- super();
- if (input != null) {
- chars = input.toCharArray();
- } else {
- chars = null;
- }
- }
-
- /**
- * Constructs a tokenizer splitting on the specified delimiter character.
- *
- * @param input the string which is to be parsed
- * @param delim the field delimiter character
- */
- public StrTokenizer(final String input, final char delim) {
- this(input);
- setDelimiterChar(delim);
- }
-
- /**
- * Constructs a tokenizer splitting on the specified delimiter string.
- *
- * @param input the string which is to be parsed
- * @param delim the field delimiter string
- */
- public StrTokenizer(final String input, final String delim) {
- this(input);
- setDelimiterString(delim);
- }
-
- /**
- * Constructs a tokenizer splitting using the specified delimiter matcher.
- *
- * @param input the string which is to be parsed
- * @param delim the field delimiter matcher
- */
- public StrTokenizer(final String input, final StrMatcher delim) {
- this(input);
- setDelimiterMatcher(delim);
- }
-
- /**
- * Constructs a tokenizer splitting on the specified delimiter character
- * and handling quotes using the specified quote character.
- *
- * @param input the string which is to be parsed
- * @param delim the field delimiter character
- * @param quote the field quoted string character
- */
- public StrTokenizer(final String input, final char delim, final char quote) {
- this(input, delim);
- setQuoteChar(quote);
- }
-
- /**
- * Constructs a tokenizer splitting using the specified delimiter matcher
- * and handling quotes using the specified quote matcher.
- *
- * @param input the string which is to be parsed
- * @param delim the field delimiter matcher
- * @param quote the field quoted string matcher
- */
- public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher quote) {
- this(input, delim);
- setQuoteMatcher(quote);
- }
-
- /**
- * Constructs a tokenizer splitting on space, tab, newline and formfeed
- * as per StringTokenizer.
- *
- * @param input the string which is to be parsed, not cloned
- */
- public StrTokenizer(final char[] input) {
- super();
- this.chars = ArrayUtils.clone(input);
- }
-
- /**
- * Constructs a tokenizer splitting on the specified character.
- *
- * @param input the string which is to be parsed, not cloned
- * @param delim the field delimiter character
- */
- public StrTokenizer(final char[] input, final char delim) {
- this(input);
- setDelimiterChar(delim);
- }
-
- /**
- * Constructs a tokenizer splitting on the specified string.
- *
- * @param input the string which is to be parsed, not cloned
- * @param delim the field delimiter string
- */
- public StrTokenizer(final char[] input, final String delim) {
- this(input);
- setDelimiterString(delim);
- }
-
- /**
- * Constructs a tokenizer splitting using the specified delimiter matcher.
- *
- * @param input the string which is to be parsed, not cloned
- * @param delim the field delimiter matcher
- */
- public StrTokenizer(final char[] input, final StrMatcher delim) {
- this(input);
- setDelimiterMatcher(delim);
- }
-
- /**
- * Constructs a tokenizer splitting on the specified delimiter character
- * and handling quotes using the specified quote character.
- *
- * @param input the string which is to be parsed, not cloned
- * @param delim the field delimiter character
- * @param quote the field quoted string character
- */
- public StrTokenizer(final char[] input, final char delim, final char quote) {
- this(input, delim);
- setQuoteChar(quote);
- }
-
- /**
- * Constructs a tokenizer splitting using the specified delimiter matcher
- * and handling quotes using the specified quote matcher.
- *
- * @param input the string which is to be parsed, not cloned
- * @param delim the field delimiter character
- * @param quote the field quoted string character
- */
- public StrTokenizer(final char[] input, final StrMatcher delim, final StrMatcher quote) {
- this(input, delim);
- setQuoteMatcher(quote);
- }
-
- // API
- //-----------------------------------------------------------------------
- /**
- * Gets the number of tokens found in the String.
- *
- * @return the number of matched tokens
- */
- public int size() {
- checkTokenized();
- return tokens.length;
- }
-
- /**
- * Gets the next token from the String.
- * Equivalent to {@link #next()} except it returns null rather than
- * throwing {@link NoSuchElementException} when no tokens remain.
- *
- * @return the next sequential token, or null when no more tokens are found
- */
- public String nextToken() {
- if (hasNext()) {
- return tokens[tokenPos++];
- }
- return null;
- }
-
- /**
- * Gets the previous token from the String.
- *
- * @return the previous sequential token, or null when no more tokens are found
- */
- public String previousToken() {
- if (hasPrevious()) {
- return tokens[--tokenPos];
- }
- return null;
- }
-
- /**
- * Gets a copy of the full token list as an independent modifiable array.
- *
- * @return the tokens as a String array
- */
- public String[] getTokenArray() {
- checkTokenized();
- return tokens.clone();
- }
-
- /**
- * Gets a copy of the full token list as an independent modifiable list.
- *
- * @return the tokens as a String array
- */
- public List getTokenList() {
- checkTokenized();
- final List list = new ArrayList<>(tokens.length);
- list.addAll(Arrays.asList(tokens));
- return list;
- }
-
- /**
- * Resets this tokenizer, forgetting all parsing and iteration already completed.
- *
- * This method allows the same tokenizer to be reused for the same String.
- *
- * @return this, to enable chaining
- */
- public StrTokenizer reset() {
- tokenPos = 0;
- tokens = null;
- return this;
- }
-
- /**
- * Reset this tokenizer, giving it a new input string to parse.
- * In this manner you can re-use a tokenizer with the same settings
- * on multiple input lines.
- *
- * @param input the new string to tokenize, null sets no text to parse
- * @return this, to enable chaining
- */
- public StrTokenizer reset(final String input) {
- reset();
- if (input != null) {
- this.chars = input.toCharArray();
- } else {
- this.chars = null;
- }
- return this;
- }
-
- /**
- * Reset this tokenizer, giving it a new input string to parse.
- * In this manner you can re-use a tokenizer with the same settings
- * on multiple input lines.
- *
- * @param input the new character array to tokenize, not cloned, null sets no text to parse
- * @return this, to enable chaining
- */
- public StrTokenizer reset(final char[] input) {
- reset();
- this.chars = ArrayUtils.clone(input);
- return this;
- }
-
- // ListIterator
- //-----------------------------------------------------------------------
- /**
- * Checks whether there are any more tokens.
- *
- * @return true if there are more tokens
- */
- @Override
- public boolean hasNext() {
- checkTokenized();
- return tokenPos < tokens.length;
- }
-
- /**
- * Gets the next token.
- *
- * @return the next String token
- * @throws NoSuchElementException if there are no more elements
- */
- @Override
- public String next() {
- if (hasNext()) {
- return tokens[tokenPos++];
- }
- throw new NoSuchElementException();
- }
-
- /**
- * Gets the index of the next token to return.
- *
- * @return the next token index
- */
- @Override
- public int nextIndex() {
- return tokenPos;
- }
-
- /**
- * Checks whether there are any previous tokens that can be iterated to.
- *
- * @return true if there are previous tokens
- */
- @Override
- public boolean hasPrevious() {
- checkTokenized();
- return tokenPos > 0;
- }
-
- /**
- * Gets the token previous to the last returned token.
- *
- * @return the previous token
- */
- @Override
- public String previous() {
- if (hasPrevious()) {
- return tokens[--tokenPos];
- }
- throw new NoSuchElementException();
- }
-
- /**
- * Gets the index of the previous token.
- *
- * @return the previous token index
- */
- @Override
- public int previousIndex() {
- return tokenPos - 1;
- }
-
- /**
- * Unsupported ListIterator operation.
- *
- * @throws UnsupportedOperationException always
- */
- @Override
- public void remove() {
- throw new UnsupportedOperationException("remove() is unsupported");
- }
-
- /**
- * Unsupported ListIterator operation.
- * @param obj this parameter ignored.
- * @throws UnsupportedOperationException always
- */
- @Override
- public void set(final String obj) {
- throw new UnsupportedOperationException("set() is unsupported");
- }
-
- /**
- * Unsupported ListIterator operation.
- * @param obj this parameter ignored.
- * @throws UnsupportedOperationException always
- */
- @Override
- public void add(final String obj) {
- throw new UnsupportedOperationException("add() is unsupported");
- }
-
- // Implementation
- //-----------------------------------------------------------------------
- /**
- * Checks if tokenization has been done, and if not then do it.
- */
- private void checkTokenized() {
- if (tokens == null) {
- if (chars == null) {
- // still call tokenize as subclass may do some work
- final List split = tokenize(null, 0, 0);
- tokens = split.toArray(new String[split.size()]);
- } else {
- final List split = tokenize(chars, 0, chars.length);
- tokens = split.toArray(new String[split.size()]);
- }
- }
- }
-
- /**
- * Internal method to performs the tokenization.
- *
- * Most users of this class do not need to call this method. This method
- * will be called automatically by other (public) methods when required.
- *
- * This method exists to allow subclasses to add code before or after the
- * tokenization. For example, a subclass could alter the character array,
- * offset or count to be parsed, or call the tokenizer multiple times on
- * multiple strings. It is also be possible to filter the results.
- *
- * StrTokenizer will always pass a zero offset and a count
- * equal to the length of the array to this method, however a subclass
- * may pass other values, or even an entirely different array.
- *
- * @param srcChars the character array being tokenized, may be null
- * @param offset the start position within the character array, must be valid
- * @param count the number of characters to tokenize, must be valid
- * @return the modifiable list of String tokens, unmodifiable if null array or zero count
- */
- protected List tokenize(final char[] srcChars, final int offset, final int count) {
- if (srcChars == null || count == 0) {
- return Collections.emptyList();
- }
- final StrBuilder buf = new StrBuilder();
- final List tokenList = new ArrayList<>();
- int pos = offset;
-
- // loop around the entire buffer
- while (pos >= 0 && pos < count) {
- // find next token
- pos = readNextToken(srcChars, pos, count, buf, tokenList);
-
- // handle case where end of string is a delimiter
- if (pos >= count) {
- addToken(tokenList, StringUtils.EMPTY);
- }
- }
- return tokenList;
- }
-
- /**
- * Adds a token to a list, paying attention to the parameters we've set.
- *
- * @param list the list to add to
- * @param tok the token to add
- */
- private void addToken(final List list, String tok) {
- if (StringUtils.isEmpty(tok)) {
- if (isIgnoreEmptyTokens()) {
- return;
- }
- if (isEmptyTokenAsNull()) {
- tok = null;
- }
- }
- list.add(tok);
- }
-
- /**
- * Reads character by character through the String to get the next token.
- *
- * @param srcChars the character array being tokenized
- * @param start the first character of field
- * @param len the length of the character array being tokenized
- * @param workArea a temporary work area
- * @param tokenList the list of parsed tokens
- * @return the starting position of the next field (the character
- * immediately after the delimiter), or -1 if end of string found
- */
- private int readNextToken(final char[] srcChars, int start, final int len, final StrBuilder workArea, final List tokenList) {
- // skip all leading whitespace, unless it is the
- // field delimiter or the quote character
- while (start < len) {
- final int removeLen = Math.max(
- getIgnoredMatcher().isMatch(srcChars, start, start, len),
- getTrimmerMatcher().isMatch(srcChars, start, start, len));
- if (removeLen == 0 ||
- getDelimiterMatcher().isMatch(srcChars, start, start, len) > 0 ||
- getQuoteMatcher().isMatch(srcChars, start, start, len) > 0) {
- break;
- }
- start += removeLen;
- }
-
- // handle reaching end
- if (start >= len) {
- addToken(tokenList, StringUtils.EMPTY);
- return -1;
- }
-
- // handle empty token
- final int delimLen = getDelimiterMatcher().isMatch(srcChars, start, start, len);
- if (delimLen > 0) {
- addToken(tokenList, StringUtils.EMPTY);
- return start + delimLen;
- }
-
- // handle found token
- final int quoteLen = getQuoteMatcher().isMatch(srcChars, start, start, len);
- if (quoteLen > 0) {
- return readWithQuotes(srcChars, start + quoteLen, len, workArea, tokenList, start, quoteLen);
- }
- return readWithQuotes(srcChars, start, len, workArea, tokenList, 0, 0);
- }
-
- /**
- * Reads a possibly quoted string token.
- *
- * @param srcChars the character array being tokenized
- * @param start the first character of field
- * @param len the length of the character array being tokenized
- * @param workArea a temporary work area
- * @param tokenList the list of parsed tokens
- * @param quoteStart the start position of the matched quote, 0 if no quoting
- * @param quoteLen the length of the matched quote, 0 if no quoting
- * @return the starting position of the next field (the character
- * immediately after the delimiter, or if end of string found,
- * then the length of string
- */
- private int readWithQuotes(final char[] srcChars, final int start, final int len, final StrBuilder workArea,
- final List tokenList, final int quoteStart, final int quoteLen) {
- // Loop until we've found the end of the quoted
- // string or the end of the input
- workArea.clear();
- int pos = start;
- boolean quoting = quoteLen > 0;
- int trimStart = 0;
-
- while (pos < len) {
- // quoting mode can occur several times throughout a string
- // we must switch between quoting and non-quoting until we
- // encounter a non-quoted delimiter, or end of string
- if (quoting) {
- // In quoting mode
-
- // If we've found a quote character, see if it's
- // followed by a second quote. If so, then we need
- // to actually put the quote character into the token
- // rather than end the token.
- if (isQuote(srcChars, pos, len, quoteStart, quoteLen)) {
- if (isQuote(srcChars, pos + quoteLen, len, quoteStart, quoteLen)) {
- // matched pair of quotes, thus an escaped quote
- workArea.append(srcChars, pos, quoteLen);
- pos += quoteLen * 2;
- trimStart = workArea.size();
- continue;
- }
-
- // end of quoting
- quoting = false;
- pos += quoteLen;
- continue;
- }
-
- // copy regular character from inside quotes
- workArea.append(srcChars[pos++]);
- trimStart = workArea.size();
-
- } else {
- // Not in quoting mode
-
- // check for delimiter, and thus end of token
- final int delimLen = getDelimiterMatcher().isMatch(srcChars, pos, start, len);
- if (delimLen > 0) {
- // return condition when end of token found
- addToken(tokenList, workArea.substring(0, trimStart));
- return pos + delimLen;
- }
-
- // check for quote, and thus back into quoting mode
- if (quoteLen > 0 && isQuote(srcChars, pos, len, quoteStart, quoteLen)) {
- quoting = true;
- pos += quoteLen;
- continue;
- }
-
- // check for ignored (outside quotes), and ignore
- final int ignoredLen = getIgnoredMatcher().isMatch(srcChars, pos, start, len);
- if (ignoredLen > 0) {
- pos += ignoredLen;
- continue;
- }
-
- // check for trimmed character
- // don't yet know if its at the end, so copy to workArea
- // use trimStart to keep track of trim at the end
- final int trimmedLen = getTrimmerMatcher().isMatch(srcChars, pos, start, len);
- if (trimmedLen > 0) {
- workArea.append(srcChars, pos, trimmedLen);
- pos += trimmedLen;
- continue;
- }
-
- // copy regular character from outside quotes
- workArea.append(srcChars[pos++]);
- trimStart = workArea.size();
- }
- }
-
- // return condition when end of string found
- addToken(tokenList, workArea.substring(0, trimStart));
- return -1;
- }
-
- /**
- * Checks if the characters at the index specified match the quote
- * already matched in readNextToken().
- *
- * @param srcChars the character array being tokenized
- * @param pos the position to check for a quote
- * @param len the length of the character array being tokenized
- * @param quoteStart the start position of the matched quote, 0 if no quoting
- * @param quoteLen the length of the matched quote, 0 if no quoting
- * @return true if a quote is matched
- */
- private boolean isQuote(final char[] srcChars, final int pos, final int len, final int quoteStart, final int quoteLen) {
- for (int i = 0; i < quoteLen; i++) {
- if (pos + i >= len || srcChars[pos + i] != srcChars[quoteStart + i]) {
- return false;
- }
- }
- return true;
- }
-
- // Delimiter
- //-----------------------------------------------------------------------
- /**
- * Gets the field delimiter matcher.
- *
- * @return the delimiter matcher in use
- */
- public StrMatcher getDelimiterMatcher() {
- return this.delimMatcher;
- }
-
- /**
- * Sets the field delimiter matcher.
- *
- * The delimiter is used to separate one token from another.
- *
- * @param delim the delimiter matcher to use
- * @return this, to enable chaining
- */
- public StrTokenizer setDelimiterMatcher(final StrMatcher delim) {
- if (delim == null) {
- this.delimMatcher = StrMatcher.noneMatcher();
- } else {
- this.delimMatcher = delim;
- }
- return this;
- }
-
- /**
- * Sets the field delimiter character.
- *
- * @param delim the delimiter character to use
- * @return this, to enable chaining
- */
- public StrTokenizer setDelimiterChar(final char delim) {
- return setDelimiterMatcher(StrMatcher.charMatcher(delim));
- }
-
- /**
- * Sets the field delimiter string.
- *
- * @param delim the delimiter string to use
- * @return this, to enable chaining
- */
- public StrTokenizer setDelimiterString(final String delim) {
- return setDelimiterMatcher(StrMatcher.stringMatcher(delim));
- }
-
- // Quote
- //-----------------------------------------------------------------------
- /**
- * Gets the quote matcher currently in use.
- *
- * The quote character is used to wrap data between the tokens.
- * This enables delimiters to be entered as data.
- * The default value is '"' (double quote).
- *
- * @return the quote matcher in use
- */
- public StrMatcher getQuoteMatcher() {
- return quoteMatcher;
- }
-
- /**
- * Set the quote matcher to use.
- *
- * The quote character is used to wrap data between the tokens.
- * This enables delimiters to be entered as data.
- *
- * @param quote the quote matcher to use, null ignored
- * @return this, to enable chaining
- */
- public StrTokenizer setQuoteMatcher(final StrMatcher quote) {
- if (quote != null) {
- this.quoteMatcher = quote;
- }
- return this;
- }
-
- /**
- * Sets the quote character to use.
- *
- * The quote character is used to wrap data between the tokens.
- * This enables delimiters to be entered as data.
- *
- * @param quote the quote character to use
- * @return this, to enable chaining
- */
- public StrTokenizer setQuoteChar(final char quote) {
- return setQuoteMatcher(StrMatcher.charMatcher(quote));
- }
-
- // Ignored
- //-----------------------------------------------------------------------
- /**
- * Gets the ignored character matcher.
- *
- * These characters are ignored when parsing the String, unless they are
- * within a quoted region.
- * The default value is not to ignore anything.
- *
- * @return the ignored matcher in use
- */
- public StrMatcher getIgnoredMatcher() {
- return ignoredMatcher;
- }
-
- /**
- * Set the matcher for characters to ignore.
- *
- * These characters are ignored when parsing the String, unless they are
- * within a quoted region.
- *
- * @param ignored the ignored matcher to use, null ignored
- * @return this, to enable chaining
- */
- public StrTokenizer setIgnoredMatcher(final StrMatcher ignored) {
- if (ignored != null) {
- this.ignoredMatcher = ignored;
- }
- return this;
- }
-
- /**
- * Set the character to ignore.
- *
- * This character is ignored when parsing the String, unless it is
- * within a quoted region.
- *
- * @param ignored the ignored character to use
- * @return this, to enable chaining
- */
- public StrTokenizer setIgnoredChar(final char ignored) {
- return setIgnoredMatcher(StrMatcher.charMatcher(ignored));
- }
-
- // Trimmer
- //-----------------------------------------------------------------------
- /**
- * Gets the trimmer character matcher.
- *
- * These characters are trimmed off on each side of the delimiter
- * until the token or quote is found.
- * The default value is not to trim anything.
- *
- * @return the trimmer matcher in use
- */
- public StrMatcher getTrimmerMatcher() {
- return trimmerMatcher;
- }
-
- /**
- * Sets the matcher for characters to trim.
- *
- * These characters are trimmed off on each side of the delimiter
- * until the token or quote is found.
- *
- * @param trimmer the trimmer matcher to use, null ignored
- * @return this, to enable chaining
- */
- public StrTokenizer setTrimmerMatcher(final StrMatcher trimmer) {
- if (trimmer != null) {
- this.trimmerMatcher = trimmer;
- }
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets whether the tokenizer currently returns empty tokens as null.
- * The default for this property is false.
- *
- * @return true if empty tokens are returned as null
- */
- public boolean isEmptyTokenAsNull() {
- return this.emptyAsNull;
- }
-
- /**
- * Sets whether the tokenizer should return empty tokens as null.
- * The default for this property is false.
- *
- * @param emptyAsNull whether empty tokens are returned as null
- * @return this, to enable chaining
- */
- public StrTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) {
- this.emptyAsNull = emptyAsNull;
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets whether the tokenizer currently ignores empty tokens.
- * The default for this property is true.
- *
- * @return true if empty tokens are not returned
- */
- public boolean isIgnoreEmptyTokens() {
- return ignoreEmptyTokens;
- }
-
- /**
- * Sets whether the tokenizer should ignore and not return empty tokens.
- * The default for this property is true.
- *
- * @param ignoreEmptyTokens whether empty tokens are not returned
- * @return this, to enable chaining
- */
- public StrTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) {
- this.ignoreEmptyTokens = ignoreEmptyTokens;
- return this;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the String content that the tokenizer is parsing.
- *
- * @return the string content being parsed
- */
- public String getContent() {
- if (chars == null) {
- return null;
- }
- return new String(chars);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Creates a new instance of this Tokenizer. The new instance is reset so
- * that it will be at the start of the token list.
- * If a {@link CloneNotSupportedException} is caught, return null.
- *
- * @return a new instance of this Tokenizer which has been reset.
- */
- @Override
- public Object clone() {
- try {
- return cloneReset();
- } catch (final CloneNotSupportedException ex) {
- return null;
- }
- }
-
- /**
- * Creates a new instance of this Tokenizer. The new instance is reset so that
- * it will be at the start of the token list.
- *
- * @return a new instance of this Tokenizer which has been reset.
- * @throws CloneNotSupportedException if there is a problem cloning
- */
- Object cloneReset() throws CloneNotSupportedException {
- // this method exists to enable 100% test coverage
- final StrTokenizer cloned = (StrTokenizer) super.clone();
- if (cloned.chars != null) {
- cloned.chars = cloned.chars.clone();
- }
- cloned.reset();
- return cloned;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets the String content that the tokenizer is parsing.
- *
- * @return the string content being parsed
- */
- @Override
- public String toString() {
- if (tokens == null) {
- return "StrTokenizer[not tokenized yet]";
- }
- return "StrTokenizer" + getTokenList();
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringEscapeUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringEscapeUtils.java
deleted file mode 100644
index 433ae7e4..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringEscapeUtils.java
+++ /dev/null
@@ -1,850 +0,0 @@
-package com.joyy.stringescape;
-
-import com.joyy.stringescape.translate.AggregateTranslator;
-import com.joyy.stringescape.translate.CharSequenceTranslator;
-import com.joyy.stringescape.translate.CsvTranslators;
-import com.joyy.stringescape.translate.EntityArrays;
-import com.joyy.stringescape.translate.JavaUnicodeEscaper;
-import com.joyy.stringescape.translate.LookupTranslator;
-import com.joyy.stringescape.translate.NumericEntityEscaper;
-import com.joyy.stringescape.translate.NumericEntityUnescaper;
-import com.joyy.stringescape.translate.OctalUnescaper;
-import com.joyy.stringescape.translate.UnicodeUnescaper;
-import com.joyy.stringescape.translate.UnicodeUnpairedSurrogateRemover;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- *
Escapes and unescapes {@code String}s for
- * Java, Java Script, HTML and XML.
- *
- * #ThreadSafe#
- *
- *
- *
- * This code has been adapted from Apache Commons Lang 3.5.
- *
- *
- * @since 1.0
- */
-public class StringEscapeUtils {
-
- /* ESCAPE TRANSLATORS */
-
- /**
- * Translator object for escaping Java.
- *
- * While {@link #escapeJava(String)} is the expected method of use, this
- * object allows the Java escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_JAVA;
- static {
- final Map escapeJavaMap = new HashMap<>();
- escapeJavaMap.put("\"", "\\\"");
- escapeJavaMap.put("\\", "\\\\");
- ESCAPE_JAVA = new AggregateTranslator(
- new LookupTranslator(Collections.unmodifiableMap(escapeJavaMap)),
- new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE),
- JavaUnicodeEscaper.outsideOf(32, 0x7f)
- );
- }
-
- /**
- * Translator object for escaping EcmaScript/JavaScript.
- *
- * While {@link #escapeEcmaScript(String)} is the expected method of use, this
- * object allows the EcmaScript escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_ECMASCRIPT;
- static {
- final Map escapeEcmaScriptMap = new HashMap<>();
- escapeEcmaScriptMap.put("'", "\\'");
- escapeEcmaScriptMap.put("\"", "\\\"");
- escapeEcmaScriptMap.put("\\", "\\\\");
- escapeEcmaScriptMap.put("/", "\\/");
- ESCAPE_ECMASCRIPT = new AggregateTranslator(
- new LookupTranslator(Collections.unmodifiableMap(escapeEcmaScriptMap)),
- new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE),
- JavaUnicodeEscaper.outsideOf(32, 0x7f)
- );
- }
-
- /**
- * Translator object for escaping Json.
- *
- * While {@link #escapeJson(String)} is the expected method of use, this
- * object allows the Json escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_JSON;
- static {
- final Map escapeJsonMap = new HashMap<>();
- escapeJsonMap.put("\"", "\\\"");
- escapeJsonMap.put("\\", "\\\\");
- escapeJsonMap.put("/", "\\/");
- ESCAPE_JSON = new AggregateTranslator(
- new LookupTranslator(Collections.unmodifiableMap(escapeJsonMap)),
- new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE),
- JavaUnicodeEscaper.outsideOf(32, 0x7e)
- );
- }
-
- /**
- * Translator object for escaping XML 1.0.
- *
- * While {@link #escapeXml10(String)} is the expected method of use, this
- * object allows the XML escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_XML10;
- static {
- final Map escapeXml10Map = new HashMap<>();
- escapeXml10Map.put("\u0000", StringUtils.EMPTY);
- escapeXml10Map.put("\u0001", StringUtils.EMPTY);
- escapeXml10Map.put("\u0002", StringUtils.EMPTY);
- escapeXml10Map.put("\u0003", StringUtils.EMPTY);
- escapeXml10Map.put("\u0004", StringUtils.EMPTY);
- escapeXml10Map.put("\u0005", StringUtils.EMPTY);
- escapeXml10Map.put("\u0006", StringUtils.EMPTY);
- escapeXml10Map.put("\u0007", StringUtils.EMPTY);
- escapeXml10Map.put("\u0008", StringUtils.EMPTY);
- escapeXml10Map.put("\u000b", StringUtils.EMPTY);
- escapeXml10Map.put("\u000c", StringUtils.EMPTY);
- escapeXml10Map.put("\u000e", StringUtils.EMPTY);
- escapeXml10Map.put("\u000f", StringUtils.EMPTY);
- escapeXml10Map.put("\u0010", StringUtils.EMPTY);
- escapeXml10Map.put("\u0011", StringUtils.EMPTY);
- escapeXml10Map.put("\u0012", StringUtils.EMPTY);
- escapeXml10Map.put("\u0013", StringUtils.EMPTY);
- escapeXml10Map.put("\u0014", StringUtils.EMPTY);
- escapeXml10Map.put("\u0015", StringUtils.EMPTY);
- escapeXml10Map.put("\u0016", StringUtils.EMPTY);
- escapeXml10Map.put("\u0017", StringUtils.EMPTY);
- escapeXml10Map.put("\u0018", StringUtils.EMPTY);
- escapeXml10Map.put("\u0019", StringUtils.EMPTY);
- escapeXml10Map.put("\u001a", StringUtils.EMPTY);
- escapeXml10Map.put("\u001b", StringUtils.EMPTY);
- escapeXml10Map.put("\u001c", StringUtils.EMPTY);
- escapeXml10Map.put("\u001d", StringUtils.EMPTY);
- escapeXml10Map.put("\u001e", StringUtils.EMPTY);
- escapeXml10Map.put("\u001f", StringUtils.EMPTY);
- escapeXml10Map.put("\ufffe", StringUtils.EMPTY);
- escapeXml10Map.put("\uffff", StringUtils.EMPTY);
- ESCAPE_XML10 = new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_ESCAPE),
- new LookupTranslator(EntityArrays.APOS_ESCAPE),
- new LookupTranslator(Collections.unmodifiableMap(escapeXml10Map)),
- NumericEntityEscaper.between(0x7f, 0x84),
- NumericEntityEscaper.between(0x86, 0x9f),
- new UnicodeUnpairedSurrogateRemover()
- );
- }
-
- /**
- * Translator object for escaping XML 1.1.
- *
- * While {@link #escapeXml11(String)} is the expected method of use, this
- * object allows the XML escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_XML11;
- static {
- final Map escapeXml11Map = new HashMap<>();
- escapeXml11Map.put("\u0000", StringUtils.EMPTY);
- escapeXml11Map.put("\u000b", "");
- escapeXml11Map.put("\u000c", "");
- escapeXml11Map.put("\ufffe", StringUtils.EMPTY);
- escapeXml11Map.put("\uffff", StringUtils.EMPTY);
- ESCAPE_XML11 = new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_ESCAPE),
- new LookupTranslator(EntityArrays.APOS_ESCAPE),
- new LookupTranslator(Collections.unmodifiableMap(escapeXml11Map)),
- NumericEntityEscaper.between(0x1, 0x8),
- NumericEntityEscaper.between(0xe, 0x1f),
- NumericEntityEscaper.between(0x7f, 0x84),
- NumericEntityEscaper.between(0x86, 0x9f),
- new UnicodeUnpairedSurrogateRemover()
- );
- }
-
- /**
- * Translator object for escaping HTML version 3.0.
- *
- * While {@link #escapeHtml3(String)} is the expected method of use, this
- * object allows the HTML escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_HTML3 =
- new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_ESCAPE),
- new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE)
- );
-
- /**
- * Translator object for escaping HTML version 4.0.
- *
- * While {@link #escapeHtml4(String)} is the expected method of use, this
- * object allows the HTML escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_HTML4 =
- new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_ESCAPE),
- new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE),
- new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE)
- );
-
- /**
- * Translator object for escaping individual Comma Separated Values.
- *
- * While {@link #escapeCsv(String)} is the expected method of use, this
- * object allows the CSV escaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator ESCAPE_CSV = new CsvTranslators.CsvEscaper();
-
- /**
- * Translator object for escaping Shell command language.
- *
- * @see Shell Command Language
- */
- public static final CharSequenceTranslator ESCAPE_XSI;
- static {
- final Map escapeXsiMap = new HashMap<>();
- escapeXsiMap.put("|", "\\|");
- escapeXsiMap.put("&", "\\&");
- escapeXsiMap.put(";", "\\;");
- escapeXsiMap.put("<", "\\<");
- escapeXsiMap.put(">", "\\>");
- escapeXsiMap.put("(", "\\(");
- escapeXsiMap.put(")", "\\)");
- escapeXsiMap.put("$", "\\$");
- escapeXsiMap.put("`", "\\`");
- escapeXsiMap.put("\\", "\\\\");
- escapeXsiMap.put("\"", "\\\"");
- escapeXsiMap.put("'", "\\'");
- escapeXsiMap.put(" ", "\\ ");
- escapeXsiMap.put("\t", "\\\t");
- escapeXsiMap.put("\r\n", "");
- escapeXsiMap.put("\n", "");
- escapeXsiMap.put("*", "\\*");
- escapeXsiMap.put("?", "\\?");
- escapeXsiMap.put("[", "\\[");
- escapeXsiMap.put("#", "\\#");
- escapeXsiMap.put("~", "\\~");
- escapeXsiMap.put("=", "\\=");
- escapeXsiMap.put("%", "\\%");
- ESCAPE_XSI = new LookupTranslator(
- Collections.unmodifiableMap(escapeXsiMap)
- );
- }
-
- /* UNESCAPE TRANSLATORS */
-
- /**
- * Translator object for unescaping escaped Java.
- *
- * While {@link #unescapeJava(String)} is the expected method of use, this
- * object allows the Java unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_JAVA;
- static {
- final Map unescapeJavaMap = new HashMap<>();
- unescapeJavaMap.put("\\\\", "\\");
- unescapeJavaMap.put("\\\"", "\"");
- unescapeJavaMap.put("\\'", "'");
- unescapeJavaMap.put("\\", "");
- UNESCAPE_JAVA = new AggregateTranslator(
- new OctalUnescaper(), // .between('\1', '\377'),
- new UnicodeUnescaper(),
- new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_UNESCAPE),
- new LookupTranslator(Collections.unmodifiableMap(unescapeJavaMap))
- );
- }
-
- /**
- * Translator object for unescaping escaped EcmaScript.
- *
- * While {@link #unescapeEcmaScript(String)} is the expected method of use, this
- * object allows the EcmaScript unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_ECMASCRIPT = UNESCAPE_JAVA;
-
- /**
- * Translator object for unescaping escaped Json.
- *
- * While {@link #unescapeJson(String)} is the expected method of use, this
- * object allows the Json unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_JSON = UNESCAPE_JAVA;
-
- /**
- * Translator object for unescaping escaped HTML 3.0.
- *
- * While {@link #unescapeHtml3(String)} is the expected method of use, this
- * object allows the HTML unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_HTML3 =
- new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_UNESCAPE),
- new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE),
- new NumericEntityUnescaper()
- );
-
- /**
- * Translator object for unescaping escaped HTML 4.0.
- *
- * While {@link #unescapeHtml4(String)} is the expected method of use, this
- * object allows the HTML unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_HTML4 =
- new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_UNESCAPE),
- new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE),
- new LookupTranslator(EntityArrays.HTML40_EXTENDED_UNESCAPE),
- new NumericEntityUnescaper()
- );
-
- /**
- * Translator object for unescaping escaped XML.
- *
- * While {@link #unescapeXml(String)} is the expected method of use, this
- * object allows the XML unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_XML =
- new AggregateTranslator(
- new LookupTranslator(EntityArrays.BASIC_UNESCAPE),
- new LookupTranslator(EntityArrays.APOS_UNESCAPE),
- new NumericEntityUnescaper()
- );
-
- /**
- * Translator object for unescaping escaped Comma Separated Value entries.
- *
- * While {@link #unescapeCsv(String)} is the expected method of use, this
- * object allows the CSV unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_CSV = new CsvTranslators.CsvUnescaper();
-
- /**
- * Translator object for unescaping escaped XSI Value entries.
- *
- * While {@link #unescapeXSI(String)} is the expected method of use, this
- * object allows the XSI unescaping functionality to be used
- * as the foundation for a custom translator.
- */
- public static final CharSequenceTranslator UNESCAPE_XSI = new XsiUnescaper();
-
- /**
- * Translator object for unescaping backslash escaped entries.
- */
- static class XsiUnescaper extends CharSequenceTranslator {
-
- /**
- * Escaped backslash constant.
- */
- private static final char BACKSLASH = '\\';
-
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
-
- if (index != 0) {
- throw new IllegalStateException("XsiUnescaper should never reach the [1] index");
- }
-
- final String s = input.toString();
-
- int segmentStart = 0;
- int searchOffset = 0;
- while (true) {
- final int pos = s.indexOf(BACKSLASH, searchOffset);
- if (pos == -1) {
- if (segmentStart < s.length()) {
- out.write(s.substring(segmentStart));
- }
- break;
- }
- if (pos > segmentStart) {
- out.write(s.substring(segmentStart, pos));
- }
- segmentStart = pos + 1;
- searchOffset = pos + 2;
- }
-
- return Character.codePointCount(input, 0, input.length());
- }
- }
-
- /* Helper functions */
-
- /**
- * {@code StringEscapeUtils} instances should NOT be constructed in
- * standard programming.
- *
- * Instead, the class should be used as:
- * StringEscapeUtils.escapeJava("foo");
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
- */
- public StringEscapeUtils() {
- super();
- }
-
- /**
- * Convenience wrapper for {@link StringBuilder} providing escape methods.
- *
- * Example:
- *
- * new Builder(ESCAPE_HTML4)
- * .append("<p>")
- * .escape("This is paragraph 1 and special chars like & get escaped.")
- * .append("</p><p>")
- * .escape("This is paragraph 2 & more...")
- * .append("</p>")
- * .toString()
- *
- *
- */
- public static final class Builder {
-
- /**
- * StringBuilder to be used in the Builder class.
- */
- private final StringBuilder sb;
-
- /**
- * CharSequenceTranslator to be used in the Builder class.
- */
- private final CharSequenceTranslator translator;
-
- /**
- * Builder constructor.
- *
- * @param translator a CharSequenceTranslator.
- */
- private Builder(final CharSequenceTranslator translator) {
- this.sb = new StringBuilder();
- this.translator = translator;
- }
-
- /**
- * Escape {@code input} according to the given {@link CharSequenceTranslator}.
- *
- * @param input the String to escape
- * @return {@code this}, to enable chaining
- */
- public Builder escape(final String input) {
- sb.append(translator.translate(input));
- return this;
- }
-
- /**
- * Literal append, no escaping being done.
- *
- * @param input the String to append
- * @return {@code this}, to enable chaining
- */
- public Builder append(final String input) {
- sb.append(input);
- return this;
- }
-
- /**
- * Return the escaped string.
- *
- * @return the escaped string
- */
- @Override
- public String toString() {
- return sb.toString();
- }
- }
-
- /**
- * Get a {@link Builder}.
- * @param translator the text translator
- * @return {@link Builder}
- */
- public static Builder builder(final CharSequenceTranslator translator) {
- return new Builder(translator);
- }
-
- // Java and JavaScript
- //--------------------------------------------------------------------------
- /**
- * Escapes the characters in a {@code String} using Java String rules.
- *
- * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
- *
- * So a tab becomes the characters {@code '\\'} and
- * {@code 't'}.
- *
- * The only difference between Java strings and JavaScript strings
- * is that in JavaScript, a single quote and forward-slash (/) are escaped.
- *
- * Example:
- *
- * input string: He didn't say, "Stop!"
- * output string: He didn't say, \"Stop!\"
- *
- *
- * @param input String to escape values in, may be null
- * @return String with escaped values, {@code null} if null string input
- */
- public static final String escapeJava(final String input) {
- return ESCAPE_JAVA.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using EcmaScript String rules.
- * Escapes any values it finds into their EcmaScript String form.
- * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
- *
- * So a tab becomes the characters {@code '\\'} and
- * {@code 't'}.
- *
- * The only difference between Java strings and EcmaScript strings
- * is that in EcmaScript, a single quote and forward-slash (/) are escaped.
- *
- * Note that EcmaScript is best known by the JavaScript and ActionScript dialects.
- *
- * Example:
- *
- * input string: He didn't say, "Stop!"
- * output string: He didn\'t say, \"Stop!\"
- *
- *
- * Security Note. We only provide backslash escaping in this method. For example, {@code '\"'} has the output
- * {@code '\\\"'} which could result in potential issues in the case where the string being escaped is being used
- * in an HTML tag like {@code }. If you wish to have more rigorous string escaping, you
- * may consider the
- * ESAPI Libraries .
- * Further, you can view the ESAPI GitHub Org .
- *
- * @param input String to escape values in, may be null
- * @return String with escaped values, {@code null} if null string input
- */
- public static final String escapeEcmaScript(final String input) {
- return ESCAPE_ECMASCRIPT.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using Json String rules.
- * Escapes any values it finds into their Json String form.
- * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
- *
- * So a tab becomes the characters {@code '\\'} and
- * {@code 't'}.
- *
- * The only difference between Java strings and Json strings
- * is that in Json, forward-slash (/) is escaped.
- *
- * See http://www.ietf.org/rfc/rfc4627.txt for further details.
- *
- * Example:
- *
- * input string: He didn't say, "Stop!"
- * output string: He didn't say, \"Stop!\"
- *
- *
- * @param input String to escape values in, may be null
- * @return String with escaped values, {@code null} if null string input
- */
- public static final String escapeJson(final String input) {
- return ESCAPE_JSON.translate(input);
- }
-
- /**
- * Unescapes any Java literals found in the {@code String}.
- * For example, it will turn a sequence of {@code '\'} and
- * {@code 'n'} into a newline character, unless the {@code '\'}
- * is preceded by another {@code '\'}.
- *
- * @param input the {@code String} to unescape, may be null
- * @return a new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeJava(final String input) {
- return UNESCAPE_JAVA.translate(input);
- }
-
- /**
- * Unescapes any EcmaScript literals found in the {@code String}.
- *
- * For example, it will turn a sequence of {@code '\'} and {@code 'n'}
- * into a newline character, unless the {@code '\'} is preceded by another
- * {@code '\'}.
- *
- * @see #unescapeJava(String)
- * @param input the {@code String} to unescape, may be null
- * @return A new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeEcmaScript(final String input) {
- return UNESCAPE_ECMASCRIPT.translate(input);
- }
-
- /**
- * Unescapes any Json literals found in the {@code String}.
- *
- * For example, it will turn a sequence of {@code '\'} and {@code 'n'}
- * into a newline character, unless the {@code '\'} is preceded by another
- * {@code '\'}.
- *
- * @see #unescapeJava(String)
- * @param input the {@code String} to unescape, may be null
- * @return A new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeJson(final String input) {
- return UNESCAPE_JSON.translate(input);
- }
-
- // HTML and XML
- //--------------------------------------------------------------------------
- /**
- * Escapes the characters in a {@code String} using HTML entities.
- *
- *
- * For example:
- *
- * "bread" & "butter"
- * becomes:
- *
- * "bread" & "butter".
- *
- *
- * Supports all known HTML 4.0 entities, including funky accents.
- * Note that the commonly used apostrophe escape character (')
- * is not a legal entity and so is not supported).
- *
- * @param input the {@code String} to escape, may be null
- * @return a new escaped {@code String}, {@code null} if null string input
- *
- * @see ISO Entities
- * @see HTML 3.2 Character Entities for ISO Latin-1
- * @see HTML 4.0 Character entity references
- * @see HTML 4.01 Character References
- * @see HTML 4.01 Code positions
- */
- public static final String escapeHtml4(final String input) {
- return ESCAPE_HTML4.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using HTML entities.
- * Supports only the HTML 3.0 entities.
- *
- * @param input the {@code String} to escape, may be null
- * @return a new escaped {@code String}, {@code null} if null string input
- */
- public static final String escapeHtml3(final String input) {
- return ESCAPE_HTML3.translate(input);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Unescapes a string containing entity escapes to a string
- * containing the actual Unicode characters corresponding to the
- * escapes. Supports HTML 4.0 entities.
- *
- * For example, the string {@code "<Français>"}
- * will become {@code ""}
- *
- * If an entity is unrecognized, it is left alone, and inserted
- * verbatim into the result string. e.g. {@code ">&zzzz;x"} will
- * become {@code ">&zzzz;x"}.
- *
- * @param input the {@code String} to unescape, may be null
- * @return a new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeHtml4(final String input) {
- return UNESCAPE_HTML4.translate(input);
- }
-
- /**
- * Unescapes a string containing entity escapes to a string
- * containing the actual Unicode characters corresponding to the
- * escapes. Supports only HTML 3.0 entities.
- *
- * @param input the {@code String} to unescape, may be null
- * @return a new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeHtml3(final String input) {
- return UNESCAPE_HTML3.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using XML entities.
- *
- * For example: {@code "bread" & "butter"} =>
- * {@code "bread" & "butter"}.
- *
- *
- * Note that XML 1.0 is a text-only format: it cannot represent control
- * characters or unpaired Unicode surrogate codepoints, even after escaping.
- * {@code escapeXml10} will remove characters that do not fit in the
- * following ranges:
- *
- * {@code #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}
- *
- * Though not strictly necessary, {@code escapeXml10} will escape
- * characters in the following ranges:
- *
- * {@code [#x7F-#x84] | [#x86-#x9F]}
- *
- * The returned string can be inserted into a valid XML 1.0 or XML 1.1
- * document. If you want to allow more non-text characters in an XML 1.1
- * document, use {@link #escapeXml11(String)}.
- *
- * @param input the {@code String} to escape, may be null
- * @return a new escaped {@code String}, {@code null} if null string input
- * @see #unescapeXml(String)
- */
- public static String escapeXml10(final String input) {
- return ESCAPE_XML10.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using XML entities.
- *
- * For example: {@code "bread" & "butter"} =>
- * {@code "bread" & "butter"}.
- *
- *
- * XML 1.1 can represent certain control characters, but it cannot represent
- * the null byte or unpaired Unicode surrogate codepoints, even after escaping.
- * {@code escapeXml11} will remove characters that do not fit in the following
- * ranges:
- *
- * {@code [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}
- *
- * {@code escapeXml11} will escape characters in the following ranges:
- *
- * {@code [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]}
- *
- * The returned string can be inserted into a valid XML 1.1 document. Do not
- * use it for XML 1.0 documents.
- *
- * @param input the {@code String} to escape, may be null
- * @return a new escaped {@code String}, {@code null} if null string input
- * @see #unescapeXml(String)
- */
- public static String escapeXml11(final String input) {
- return ESCAPE_XML11.translate(input);
- }
-
- //-----------------------------------------------------------------------
- /**
- * Unescapes a string containing XML entity escapes to a string
- * containing the actual Unicode characters corresponding to the
- * escapes.
- *
- * Supports only the five basic XML entities (gt, lt, quot, amp, apos).
- * Does not support DTDs or external entities.
- *
- * Note that numerical \\u Unicode codes are unescaped to their respective
- * Unicode characters. This may change in future releases.
- *
- * @param input the {@code String} to unescape, may be null
- * @return a new unescaped {@code String}, {@code null} if null string input
- * @see #escapeXml10(String)
- * @see #escapeXml11(String)
- */
- public static final String unescapeXml(final String input) {
- return UNESCAPE_XML.translate(input);
- }
-
- //-----------------------------------------------------------------------
-
- /**
- * Returns a {@code String} value for a CSV column enclosed in double quotes,
- * if required.
- *
- * If the value contains a comma, newline or double quote, then the
- * String value is returned enclosed in double quotes.
- *
- * Any double quote characters in the value are escaped with another double quote.
- *
- * If the value does not contain a comma, newline or double quote, then the
- * String value is returned unchanged.
- *
- * see Wikipedia and
- * RFC 4180 .
- *
- * @param input the input CSV column String, may be null
- * @return the input String, enclosed in double quotes if the value contains a comma,
- * newline or double quote, {@code null} if null string input
- */
- public static final String escapeCsv(final String input) {
- return ESCAPE_CSV.translate(input);
- }
-
- /**
- * Returns a {@code String} value for an unescaped CSV column.
- *
- * If the value is enclosed in double quotes, and contains a comma, newline
- * or double quote, then quotes are removed.
- *
- *
- * Any double quote escaped characters (a pair of double quotes) are unescaped
- * to just one double quote.
- *
- * If the value is not enclosed in double quotes, or is and does not contain a
- * comma, newline or double quote, then the String value is returned unchanged.
- *
- * see Wikipedia and
- * RFC 4180 .
- *
- * @param input the input CSV column String, may be null
- * @return the input String, with enclosing double quotes removed and embedded double
- * quotes unescaped, {@code null} if null string input
- */
- public static final String unescapeCsv(final String input) {
- return UNESCAPE_CSV.translate(input);
- }
-
- /**
- * Escapes the characters in a {@code String} using XSI rules.
- *
- * Beware! In most cases you don't want to escape shell commands but use multi-argument
- * methods provided by {@link ProcessBuilder} or {@link Runtime#exec(String[])}
- * instead.
- *
- * Example:
- *
- * input string: He didn't say, "Stop!"
- * output string: He\ didn\'t\ say,\ \"Stop!\"
- *
- *
- * @see Shell Command Language
- * @param input String to escape values in, may be null
- * @return String with escaped values, {@code null} if null string input
- */
- public static final String escapeXSI(final String input) {
- return ESCAPE_XSI.translate(input);
- }
-
- /**
- * Unescapes the characters in a {@code String} using XSI rules.
- *
- * @see StringEscapeUtils#escapeXSI(String)
- * @param input the {@code String} to unescape, may be null
- * @return a new unescaped {@code String}, {@code null} if null string input
- */
- public static final String unescapeXSI(final String input) {
- return UNESCAPE_XSI.translate(input);
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringUtils.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringUtils.java
deleted file mode 100644
index 2123ef21..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/StringUtils.java
+++ /dev/null
@@ -1,9413 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.text.Normalizer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Operations on {@link String} that are
- * {@code null} safe.
- *
- *
- * IsEmpty/IsBlank
- * - checks if a String contains text
- * Trim/Strip
- * - removes leading and trailing whitespace
- * Equals/Compare
- * - compares two strings null-safe
- * startsWith
- * - check if a String starts with a prefix null-safe
- * endsWith
- * - check if a String ends with a suffix null-safe
- * IndexOf/LastIndexOf/Contains
- * - null-safe index-of checks
- * IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut
- * - index-of any of a set of Strings
- * ContainsOnly/ContainsNone/ContainsAny
- * - does String contains only/none/any of these characters
- * Substring/Left/Right/Mid
- * - null-safe substring extractions
- * SubstringBefore/SubstringAfter/SubstringBetween
- * - substring extraction relative to other strings
- * Split/Join
- * - splits a String into an array of substrings and vice versa
- * Remove/Delete
- * - removes part of a String
- * Replace/Overlay
- * - Searches a String and replaces one String with another
- * Chomp/Chop
- * - removes the last part of a String
- * AppendIfMissing
- * - appends a suffix to the end of the String if not present
- * PrependIfMissing
- * - prepends a prefix to the start of the String if not present
- * LeftPad/RightPad/Center/Repeat
- * - pads a String
- * UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize
- * - changes the case of a String
- * CountMatches
- * - counts the number of occurrences of one String in another
- * IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable
- * - checks the characters in a String
- * DefaultString
- * - protects against a null input String
- * Rotate
- * - rotate (circular shift) a String
- * Reverse/ReverseDelimited
- * - reverses a String
- * Abbreviate
- * - abbreviates a string using ellipsis or another given String
- * Difference
- * - compares Strings and reports on their differences
- * LevenshteinDistance
- * - the number of changes needed to change one String into another
- *
- *
- * The {@code StringUtils} class defines certain words related to
- * String handling.
- *
- *
- * null - {@code null}
- * empty - a zero-length string ({@code ""})
- * space - the space character ({@code ' '}, char 32)
- * whitespace - the characters defined by {@link Character#isWhitespace(char)}
- * trim - the characters <= 32 as in {@link String#trim()}
- *
- *
- * {@code StringUtils} handles {@code null} input Strings quietly.
- * That is to say that a {@code null} input will return {@code null}.
- * Where a {@code boolean} or {@code int} is being returned
- * details vary by method.
- *
- * A side effect of the {@code null} handling is that a
- * {@code NullPointerException} should be considered a bug in
- * {@code StringUtils}.
- *
- * Methods in this class give sample code to explain their operation.
- * The symbol {@code *} is used to indicate any input including {@code null}.
- *
- * #ThreadSafe#
- * @see String
- * @since 1.0
- */
-//@Immutable
-public class StringUtils {
-
- private static final int STRING_BUILDER_SIZE = 256;
-
- // Performance testing notes (JDK 1.4, Jul03, scolebourne)
- // Whitespace:
- // Character.isWhitespace() is faster than WHITESPACE.indexOf()
- // where WHITESPACE is a string of all whitespace characters
- //
- // Character access:
- // String.charAt(n) versus toCharArray(), then array[n]
- // String.charAt(n) is about 15% worse for a 10K string
- // They are about equal for a length 50 string
- // String.charAt(n) is about 4 times better for a length 3 string
- // String.charAt(n) is best bet overall
- //
- // Append:
- // String.concat about twice as fast as StringBuffer.append
- // (not sure who tested this)
-
- /**
- * A String for a space character.
- *
- * @since 3.2
- */
- public static final String SPACE = " ";
-
- /**
- * The empty String {@code ""}.
- * @since 2.0
- */
- public static final String EMPTY = "";
-
- /**
- * A String for linefeed LF ("\n").
- *
- * @see JLF: Escape Sequences
- * for Character and String Literals
- * @since 3.2
- */
- public static final String LF = "\n";
-
- /**
- * A String for carriage return CR ("\r").
- *
- * @see JLF: Escape Sequences
- * for Character and String Literals
- * @since 3.2
- */
- public static final String CR = "\r";
-
- /**
- * Represents a failed index search.
- * @since 2.1
- */
- public static final int INDEX_NOT_FOUND = -1;
-
- /**
- * The maximum size to which the padding constant(s) can expand.
- */
- private static final int PAD_LIMIT = 8192;
-
- /**
- * {@code StringUtils} instances should NOT be constructed in
- * standard programming. Instead, the class should be used as
- * {@code StringUtils.trim(" foo ");}.
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
- */
- public StringUtils() {
- super();
- }
-
- // Empty checks
- //-----------------------------------------------------------------------
- /**
- * Checks if a CharSequence is empty ("") or null.
- *
- *
- * StringUtils.isEmpty(null) = true
- * StringUtils.isEmpty("") = true
- * StringUtils.isEmpty(" ") = false
- * StringUtils.isEmpty("bob") = false
- * StringUtils.isEmpty(" bob ") = false
- *
- *
- * NOTE: This method changed in Lang version 2.0.
- * It no longer trims the CharSequence.
- * That functionality is available in isBlank().
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if the CharSequence is empty or null
- * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
- */
- public static boolean isEmpty(final CharSequence cs) {
- return cs == null || cs.length() == 0;
- }
-
- /**
- * Checks if a CharSequence is not empty ("") and not null.
- *
- *
- * StringUtils.isNotEmpty(null) = false
- * StringUtils.isNotEmpty("") = false
- * StringUtils.isNotEmpty(" ") = true
- * StringUtils.isNotEmpty("bob") = true
- * StringUtils.isNotEmpty(" bob ") = true
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if the CharSequence is not empty and not null
- * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
- */
- public static boolean isNotEmpty(final CharSequence cs) {
- return !isEmpty(cs);
- }
-
- /**
- * Checks if any of the CharSequences are empty ("") or null.
- *
- *
- * StringUtils.isAnyEmpty((String) null) = true
- * StringUtils.isAnyEmpty((String[]) null) = false
- * StringUtils.isAnyEmpty(null, "foo") = true
- * StringUtils.isAnyEmpty("", "bar") = true
- * StringUtils.isAnyEmpty("bob", "") = true
- * StringUtils.isAnyEmpty(" bob ", null) = true
- * StringUtils.isAnyEmpty(" ", "bar") = false
- * StringUtils.isAnyEmpty("foo", "bar") = false
- * StringUtils.isAnyEmpty(new String[]{}) = false
- * StringUtils.isAnyEmpty(new String[]{""}) = true
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if any of the CharSequences are empty or null
- * @since 3.2
- */
- public static boolean isAnyEmpty(final CharSequence... css) {
- if (ArrayUtils.isEmpty(css)) {
- return false;
- }
- for (final CharSequence cs : css){
- if (isEmpty(cs)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if none of the CharSequences are empty ("") or null.
- *
- *
- * StringUtils.isNoneEmpty((String) null) = false
- * StringUtils.isNoneEmpty((String[]) null) = true
- * StringUtils.isNoneEmpty(null, "foo") = false
- * StringUtils.isNoneEmpty("", "bar") = false
- * StringUtils.isNoneEmpty("bob", "") = false
- * StringUtils.isNoneEmpty(" bob ", null) = false
- * StringUtils.isNoneEmpty(new String[] {}) = true
- * StringUtils.isNoneEmpty(new String[]{""}) = false
- * StringUtils.isNoneEmpty(" ", "bar") = true
- * StringUtils.isNoneEmpty("foo", "bar") = true
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if none of the CharSequences are empty or null
- * @since 3.2
- */
- public static boolean isNoneEmpty(final CharSequence... css) {
- return !isAnyEmpty(css);
- }
-
- /**
- * Checks if all of the CharSequences are empty ("") or null.
- *
- *
- * StringUtils.isAllEmpty(null) = true
- * StringUtils.isAllEmpty(null, "") = true
- * StringUtils.isAllEmpty(new String[] {}) = true
- * StringUtils.isAllEmpty(null, "foo") = false
- * StringUtils.isAllEmpty("", "bar") = false
- * StringUtils.isAllEmpty("bob", "") = false
- * StringUtils.isAllEmpty(" bob ", null) = false
- * StringUtils.isAllEmpty(" ", "bar") = false
- * StringUtils.isAllEmpty("foo", "bar") = false
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if all of the CharSequences are empty or null
- * @since 3.6
- */
- public static boolean isAllEmpty(final CharSequence... css) {
- if (ArrayUtils.isEmpty(css)) {
- return true;
- }
- for (final CharSequence cs : css) {
- if (isNotEmpty(cs)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if a CharSequence is empty (""), null or whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.isBlank(null) = true
- * StringUtils.isBlank("") = true
- * StringUtils.isBlank(" ") = true
- * StringUtils.isBlank("bob") = false
- * StringUtils.isBlank(" bob ") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if the CharSequence is null, empty or whitespace only
- * @since 2.0
- * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
- */
- public static boolean isBlank(final CharSequence cs) {
- int strLen;
- if (cs == null || (strLen = cs.length()) == 0) {
- return true;
- }
- for (int i = 0; i < strLen; i++) {
- if (!Character.isWhitespace(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if a CharSequence is not empty (""), not null and not whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.isNotBlank(null) = false
- * StringUtils.isNotBlank("") = false
- * StringUtils.isNotBlank(" ") = false
- * StringUtils.isNotBlank("bob") = true
- * StringUtils.isNotBlank(" bob ") = true
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if the CharSequence is
- * not empty and not null and not whitespace only
- * @since 2.0
- * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
- */
- public static boolean isNotBlank(final CharSequence cs) {
- return !isBlank(cs);
- }
-
- /**
- * Checks if any of the CharSequences are empty ("") or null or whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.isAnyBlank((String) null) = true
- * StringUtils.isAnyBlank((String[]) null) = false
- * StringUtils.isAnyBlank(null, "foo") = true
- * StringUtils.isAnyBlank(null, null) = true
- * StringUtils.isAnyBlank("", "bar") = true
- * StringUtils.isAnyBlank("bob", "") = true
- * StringUtils.isAnyBlank(" bob ", null) = true
- * StringUtils.isAnyBlank(" ", "bar") = true
- * StringUtils.isAnyBlank(new String[] {}) = false
- * StringUtils.isAnyBlank(new String[]{""}) = true
- * StringUtils.isAnyBlank("foo", "bar") = false
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if any of the CharSequences are empty or null or whitespace only
- * @since 3.2
- */
- public static boolean isAnyBlank(final CharSequence... css) {
- if (ArrayUtils.isEmpty(css)) {
- return false;
- }
- for (final CharSequence cs : css){
- if (isBlank(cs)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if none of the CharSequences are empty (""), null or whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.isNoneBlank((String) null) = false
- * StringUtils.isNoneBlank((String[]) null) = true
- * StringUtils.isNoneBlank(null, "foo") = false
- * StringUtils.isNoneBlank(null, null) = false
- * StringUtils.isNoneBlank("", "bar") = false
- * StringUtils.isNoneBlank("bob", "") = false
- * StringUtils.isNoneBlank(" bob ", null) = false
- * StringUtils.isNoneBlank(" ", "bar") = false
- * StringUtils.isNoneBlank(new String[] {}) = true
- * StringUtils.isNoneBlank(new String[]{""}) = false
- * StringUtils.isNoneBlank("foo", "bar") = true
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if none of the CharSequences are empty or null or whitespace only
- * @since 3.2
- */
- public static boolean isNoneBlank(final CharSequence... css) {
- return !isAnyBlank(css);
- }
-
- /**
- * Checks if all of the CharSequences are empty (""), null or whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.isAllBlank(null) = true
- * StringUtils.isAllBlank(null, "foo") = false
- * StringUtils.isAllBlank(null, null) = true
- * StringUtils.isAllBlank("", "bar") = false
- * StringUtils.isAllBlank("bob", "") = false
- * StringUtils.isAllBlank(" bob ", null) = false
- * StringUtils.isAllBlank(" ", "bar") = false
- * StringUtils.isAllBlank("foo", "bar") = false
- * StringUtils.isAllBlank(new String[] {}) = true
- *
- *
- * @param css the CharSequences to check, may be null or empty
- * @return {@code true} if all of the CharSequences are empty or null or whitespace only
- * @since 3.6
- */
- public static boolean isAllBlank(final CharSequence... css) {
- if (ArrayUtils.isEmpty(css)) {
- return true;
- }
- for (final CharSequence cs : css) {
- if (isNotBlank(cs)) {
- return false;
- }
- }
- return true;
- }
-
- // Trim
- //-----------------------------------------------------------------------
- /**
- * Removes control characters (char <= 32) from both
- * ends of this String, handling {@code null} by returning
- * {@code null}.
- *
- * The String is trimmed using {@link String#trim()}.
- * Trim removes start and end characters <= 32.
- * To strip whitespace use {@link #strip(String)}.
- *
- * To trim your choice of characters, use the
- * {@link #strip(String, String)} methods.
- *
- *
- * StringUtils.trim(null) = null
- * StringUtils.trim("") = ""
- * StringUtils.trim(" ") = ""
- * StringUtils.trim("abc") = "abc"
- * StringUtils.trim(" abc ") = "abc"
- *
- *
- * @param str the String to be trimmed, may be null
- * @return the trimmed string, {@code null} if null String input
- */
- public static String trim(final String str) {
- return str == null ? null : str.trim();
- }
-
- /**
- * Removes control characters (char <= 32) from both
- * ends of this String returning {@code null} if the String is
- * empty ("") after the trim or if it is {@code null}.
- *
- *
The String is trimmed using {@link String#trim()}.
- * Trim removes start and end characters <= 32.
- * To strip whitespace use {@link #stripToNull(String)}.
- *
- *
- * StringUtils.trimToNull(null) = null
- * StringUtils.trimToNull("") = null
- * StringUtils.trimToNull(" ") = null
- * StringUtils.trimToNull("abc") = "abc"
- * StringUtils.trimToNull(" abc ") = "abc"
- *
- *
- * @param str the String to be trimmed, may be null
- * @return the trimmed String,
- * {@code null} if only chars <= 32, empty or null String input
- * @since 2.0
- */
- public static String trimToNull(final String str) {
- final String ts = trim(str);
- return isEmpty(ts) ? null : ts;
- }
-
- /**
- * Removes control characters (char <= 32) from both
- * ends of this String returning an empty String ("") if the String
- * is empty ("") after the trim or if it is {@code null}.
- *
- *
The String is trimmed using {@link String#trim()}.
- * Trim removes start and end characters <= 32.
- * To strip whitespace use {@link #stripToEmpty(String)}.
- *
- *
- * StringUtils.trimToEmpty(null) = ""
- * StringUtils.trimToEmpty("") = ""
- * StringUtils.trimToEmpty(" ") = ""
- * StringUtils.trimToEmpty("abc") = "abc"
- * StringUtils.trimToEmpty(" abc ") = "abc"
- *
- *
- * @param str the String to be trimmed, may be null
- * @return the trimmed String, or an empty String if {@code null} input
- * @since 2.0
- */
- public static String trimToEmpty(final String str) {
- return str == null ? EMPTY : str.trim();
- }
-
- /**
- * Truncates a String. This will turn
- * "Now is the time for all good men" into "Now is the time for".
- *
- * Specifically:
- *
- * If {@code str} is less than {@code maxWidth} characters
- * long, return it.
- * Else truncate it to {@code substring(str, 0, maxWidth)}.
- * If {@code maxWidth} is less than {@code 0}, throw an
- * {@code IllegalArgumentException}.
- * In no case will it return a String of length greater than
- * {@code maxWidth}.
- *
- *
- *
- * StringUtils.truncate(null, 0) = null
- * StringUtils.truncate(null, 2) = null
- * StringUtils.truncate("", 4) = ""
- * StringUtils.truncate("abcdefg", 4) = "abcd"
- * StringUtils.truncate("abcdefg", 6) = "abcdef"
- * StringUtils.truncate("abcdefg", 7) = "abcdefg"
- * StringUtils.truncate("abcdefg", 8) = "abcdefg"
- * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
- *
- *
- * @param str the String to truncate, may be null
- * @param maxWidth maximum length of result String, must be positive
- * @return truncated String, {@code null} if null String input
- * @since 3.5
- */
- public static String truncate(final String str, final int maxWidth) {
- return truncate(str, 0, maxWidth);
- }
-
- /**
- * Truncates a String. This will turn
- * "Now is the time for all good men" into "is the time for all".
- *
- * Works like {@code truncate(String, int)}, but allows you to specify
- * a "left edge" offset.
- *
- *
Specifically:
- *
- * If {@code str} is less than {@code maxWidth} characters
- * long, return it.
- * Else truncate it to {@code substring(str, offset, maxWidth)}.
- * If {@code maxWidth} is less than {@code 0}, throw an
- * {@code IllegalArgumentException}.
- * If {@code offset} is less than {@code 0}, throw an
- * {@code IllegalArgumentException}.
- * In no case will it return a String of length greater than
- * {@code maxWidth}.
- *
- *
- *
- * StringUtils.truncate(null, 0, 0) = null
- * StringUtils.truncate(null, 2, 4) = null
- * StringUtils.truncate("", 0, 10) = ""
- * StringUtils.truncate("", 2, 10) = ""
- * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
- * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
- * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
- * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
- * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
- * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = "abcdefghij"
- * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = "abcdefghijklmno"
- * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
- * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
- * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
- * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
- * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
- * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
- * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
- * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
- * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
- * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
- * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
- * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
- * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
- * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
- * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
- * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
- * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
- * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
- * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
- *
- *
- * @param str the String to check, may be null
- * @param offset left edge of source String
- * @param maxWidth maximum length of result String, must be positive
- * @return truncated String, {@code null} if null String input
- * @since 3.5
- */
- public static String truncate(final String str, final int offset, final int maxWidth) {
- if (offset < 0) {
- throw new IllegalArgumentException("offset cannot be negative");
- }
- if (maxWidth < 0) {
- throw new IllegalArgumentException("maxWith cannot be negative");
- }
- if (str == null) {
- return null;
- }
- if (offset > str.length()) {
- return EMPTY;
- }
- if (str.length() > maxWidth) {
- final int ix = offset + maxWidth > str.length() ? str.length() : offset + maxWidth;
- return str.substring(offset, ix);
- }
- return str.substring(offset);
- }
-
- // Stripping
- //-----------------------------------------------------------------------
- /**
- * Strips whitespace from the start and end of a String.
- *
- * This is similar to {@link #trim(String)} but removes whitespace.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.strip(null) = null
- * StringUtils.strip("") = ""
- * StringUtils.strip(" ") = ""
- * StringUtils.strip("abc") = "abc"
- * StringUtils.strip(" abc") = "abc"
- * StringUtils.strip("abc ") = "abc"
- * StringUtils.strip(" abc ") = "abc"
- * StringUtils.strip(" ab c ") = "ab c"
- *
- *
- * @param str the String to remove whitespace from, may be null
- * @return the stripped String, {@code null} if null String input
- */
- public static String strip(final String str) {
- return strip(str, null);
- }
-
- /**
- * Strips whitespace from the start and end of a String returning
- * {@code null} if the String is empty ("") after the strip.
- *
- * This is similar to {@link #trimToNull(String)} but removes whitespace.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.stripToNull(null) = null
- * StringUtils.stripToNull("") = null
- * StringUtils.stripToNull(" ") = null
- * StringUtils.stripToNull("abc") = "abc"
- * StringUtils.stripToNull(" abc") = "abc"
- * StringUtils.stripToNull("abc ") = "abc"
- * StringUtils.stripToNull(" abc ") = "abc"
- * StringUtils.stripToNull(" ab c ") = "ab c"
- *
- *
- * @param str the String to be stripped, may be null
- * @return the stripped String,
- * {@code null} if whitespace, empty or null String input
- * @since 2.0
- */
- public static String stripToNull(String str) {
- if (str == null) {
- return null;
- }
- str = strip(str, null);
- return str.isEmpty() ? null : str;
- }
-
- /**
- * Strips whitespace from the start and end of a String returning
- * an empty String if {@code null} input.
- *
- * This is similar to {@link #trimToEmpty(String)} but removes whitespace.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.stripToEmpty(null) = ""
- * StringUtils.stripToEmpty("") = ""
- * StringUtils.stripToEmpty(" ") = ""
- * StringUtils.stripToEmpty("abc") = "abc"
- * StringUtils.stripToEmpty(" abc") = "abc"
- * StringUtils.stripToEmpty("abc ") = "abc"
- * StringUtils.stripToEmpty(" abc ") = "abc"
- * StringUtils.stripToEmpty(" ab c ") = "ab c"
- *
- *
- * @param str the String to be stripped, may be null
- * @return the trimmed String, or an empty String if {@code null} input
- * @since 2.0
- */
- public static String stripToEmpty(final String str) {
- return str == null ? EMPTY : strip(str, null);
- }
-
- /**
- * Strips any of a set of characters from the start and end of a String.
- * This is similar to {@link String#trim()} but allows the characters
- * to be stripped to be controlled.
- *
- * A {@code null} input String returns {@code null}.
- * An empty string ("") input returns the empty string.
- *
- * If the stripChars String is {@code null}, whitespace is
- * stripped as defined by {@link Character#isWhitespace(char)}.
- * Alternatively use {@link #strip(String)}.
- *
- *
- * StringUtils.strip(null, *) = null
- * StringUtils.strip("", *) = ""
- * StringUtils.strip("abc", null) = "abc"
- * StringUtils.strip(" abc", null) = "abc"
- * StringUtils.strip("abc ", null) = "abc"
- * StringUtils.strip(" abc ", null) = "abc"
- * StringUtils.strip(" abcyx", "xyz") = " abc"
- *
- *
- * @param str the String to remove characters from, may be null
- * @param stripChars the characters to remove, null treated as whitespace
- * @return the stripped String, {@code null} if null String input
- */
- public static String strip(String str, final String stripChars) {
- if (isEmpty(str)) {
- return str;
- }
- str = stripStart(str, stripChars);
- return stripEnd(str, stripChars);
- }
-
- /**
- * Strips any of a set of characters from the start of a String.
- *
- * A {@code null} input String returns {@code null}.
- * An empty string ("") input returns the empty string.
- *
- * If the stripChars String is {@code null}, whitespace is
- * stripped as defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.stripStart(null, *) = null
- * StringUtils.stripStart("", *) = ""
- * StringUtils.stripStart("abc", "") = "abc"
- * StringUtils.stripStart("abc", null) = "abc"
- * StringUtils.stripStart(" abc", null) = "abc"
- * StringUtils.stripStart("abc ", null) = "abc "
- * StringUtils.stripStart(" abc ", null) = "abc "
- * StringUtils.stripStart("yxabc ", "xyz") = "abc "
- *
- *
- * @param str the String to remove characters from, may be null
- * @param stripChars the characters to remove, null treated as whitespace
- * @return the stripped String, {@code null} if null String input
- */
- public static String stripStart(final String str, final String stripChars) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
- return str;
- }
- int start = 0;
- if (stripChars == null) {
- while (start != strLen && Character.isWhitespace(str.charAt(start))) {
- start++;
- }
- } else if (stripChars.isEmpty()) {
- return str;
- } else {
- while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
- start++;
- }
- }
- return str.substring(start);
- }
-
- /**
- * Strips any of a set of characters from the end of a String.
- *
- * A {@code null} input String returns {@code null}.
- * An empty string ("") input returns the empty string.
- *
- * If the stripChars String is {@code null}, whitespace is
- * stripped as defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.stripEnd(null, *) = null
- * StringUtils.stripEnd("", *) = ""
- * StringUtils.stripEnd("abc", "") = "abc"
- * StringUtils.stripEnd("abc", null) = "abc"
- * StringUtils.stripEnd(" abc", null) = " abc"
- * StringUtils.stripEnd("abc ", null) = "abc"
- * StringUtils.stripEnd(" abc ", null) = " abc"
- * StringUtils.stripEnd(" abcyx", "xyz") = " abc"
- * StringUtils.stripEnd("120.00", ".0") = "12"
- *
- *
- * @param str the String to remove characters from, may be null
- * @param stripChars the set of characters to remove, null treated as whitespace
- * @return the stripped String, {@code null} if null String input
- */
- public static String stripEnd(final String str, final String stripChars) {
- int end;
- if (str == null || (end = str.length()) == 0) {
- return str;
- }
-
- if (stripChars == null) {
- while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
- end--;
- }
- } else if (stripChars.isEmpty()) {
- return str;
- } else {
- while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
- end--;
- }
- }
- return str.substring(0, end);
- }
-
- // StripAll
- //-----------------------------------------------------------------------
- /**
- * Strips whitespace from the start and end of every String in an array.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * A new array is returned each time, except for length zero.
- * A {@code null} array will return {@code null}.
- * An empty array will return itself.
- * A {@code null} array entry will be ignored.
- *
- *
- * StringUtils.stripAll(null) = null
- * StringUtils.stripAll([]) = []
- * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
- * StringUtils.stripAll(["abc ", null]) = ["abc", null]
- *
- *
- * @param strs the array to remove whitespace from, may be null
- * @return the stripped Strings, {@code null} if null array input
- */
- public static String[] stripAll(final String... strs) {
- return stripAll(strs, null);
- }
-
- /**
- * Strips any of a set of characters from the start and end of every
- * String in an array.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * A new array is returned each time, except for length zero.
- * A {@code null} array will return {@code null}.
- * An empty array will return itself.
- * A {@code null} array entry will be ignored.
- * A {@code null} stripChars will strip whitespace as defined by
- * {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.stripAll(null, *) = null
- * StringUtils.stripAll([], *) = []
- * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]
- * StringUtils.stripAll(["abc ", null], null) = ["abc", null]
- * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
- * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
- *
- *
- * @param strs the array to remove characters from, may be null
- * @param stripChars the characters to remove, null treated as whitespace
- * @return the stripped Strings, {@code null} if null array input
- */
- public static String[] stripAll(final String[] strs, final String stripChars) {
- int strsLen;
- if (strs == null || (strsLen = strs.length) == 0) {
- return strs;
- }
- final String[] newArr = new String[strsLen];
- for (int i = 0; i < strsLen; i++) {
- newArr[i] = strip(strs[i], stripChars);
- }
- return newArr;
- }
-
- /**
- * Removes diacritics (~= accents) from a string. The case will not be altered.
- * For instance, 'à' will be replaced by 'a'.
- * Note that ligatures will be left as is.
- *
- *
- * StringUtils.stripAccents(null) = null
- * StringUtils.stripAccents("") = ""
- * StringUtils.stripAccents("control") = "control"
- * StringUtils.stripAccents("éclair") = "eclair"
- *
- *
- * @param input String to be stripped
- * @return input text with diacritics removed
- *
- * @since 3.0
- */
- // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
- public static String stripAccents(final String input) {
- if(input == null) {
- return null;
- }
- final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");//$NON-NLS-1$
- final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));
- convertRemainingAccentCharacters(decomposed);
- // Note that this doesn't correctly remove ligatures...
- return pattern.matcher(decomposed).replaceAll(EMPTY);
- }
-
- private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
- for (int i = 0; i < decomposed.length(); i++) {
- if (decomposed.charAt(i) == '\u0141') {
- decomposed.deleteCharAt(i);
- decomposed.insert(i, 'L');
- } else if (decomposed.charAt(i) == '\u0142') {
- decomposed.deleteCharAt(i);
- decomposed.insert(i, 'l');
- }
- }
- }
-
- // Equals
- //-----------------------------------------------------------------------
- /**
- * Compares two CharSequences, returning {@code true} if they represent
- * equal sequences of characters.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case sensitive.
- *
- *
- * StringUtils.equals(null, null) = true
- * StringUtils.equals(null, "abc") = false
- * StringUtils.equals("abc", null) = false
- * StringUtils.equals("abc", "abc") = true
- * StringUtils.equals("abc", "ABC") = false
- *
- *
- * @see Object#equals(Object)
- * @param cs1 the first CharSequence, may be {@code null}
- * @param cs2 the second CharSequence, may be {@code null}
- * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
- * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
- */
- public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
- if (cs1 == cs2) {
- return true;
- }
- if (cs1 == null || cs2 == null) {
- return false;
- }
- if (cs1.length() != cs2.length()) {
- return false;
- }
- if (cs1 instanceof String && cs2 instanceof String) {
- return cs1.equals(cs2);
- }
- return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, cs1.length());
- }
-
- /**
- * Compares two CharSequences, returning {@code true} if they represent
- * equal sequences of characters, ignoring case.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered equal. Comparison is case insensitive.
- *
- *
- * StringUtils.equalsIgnoreCase(null, null) = true
- * StringUtils.equalsIgnoreCase(null, "abc") = false
- * StringUtils.equalsIgnoreCase("abc", null) = false
- * StringUtils.equalsIgnoreCase("abc", "abc") = true
- * StringUtils.equalsIgnoreCase("abc", "ABC") = true
- *
- *
- * @param str1 the first CharSequence, may be null
- * @param str2 the second CharSequence, may be null
- * @return {@code true} if the CharSequence are equal, case insensitive, or
- * both {@code null}
- * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
- */
- public static boolean equalsIgnoreCase(final CharSequence str1, final CharSequence str2) {
- if (str1 == null || str2 == null) {
- return str1 == str2;
- } else if (str1 == str2) {
- return true;
- } else if (str1.length() != str2.length()) {
- return false;
- } else {
- return CharSequenceUtils.regionMatches(str1, true, 0, str2, 0, str1.length());
- }
- }
-
- // Compare
- //-----------------------------------------------------------------------
- /**
- * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
- *
- * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
- * {@code int < 0}, if {@code str1} is less than {@code str2}
- * {@code int > 0}, if {@code str1} is greater than {@code str2}
- *
- *
- * This is a {@code null} safe version of :
- * str1.compareTo(str2)
- *
- * {@code null} value is considered less than non-{@code null} value.
- * Two {@code null} references are considered equal.
- *
- *
- * StringUtils.compare(null, null) = 0
- * StringUtils.compare(null , "a") < 0
- * StringUtils.compare("a", null) > 0
- * StringUtils.compare("abc", "abc") = 0
- * StringUtils.compare("a", "b") < 0
- * StringUtils.compare("b", "a") > 0
- * StringUtils.compare("a", "B") > 0
- * StringUtils.compare("ab", "abc") < 0
- *
- *
- * @see #compare(String, String, boolean)
- * @see String#compareTo(String)
- * @param str1 the String to compare from
- * @param str2 the String to compare to
- * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2}
- * @since 3.5
- */
- public static int compare(final String str1, final String str2) {
- return compare(str1, str2, true);
- }
-
- /**
- * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
- *
- * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
- * {@code int < 0}, if {@code str1} is less than {@code str2}
- * {@code int > 0}, if {@code str1} is greater than {@code str2}
- *
- *
- * This is a {@code null} safe version of :
- * str1.compareTo(str2)
- *
- * {@code null} inputs are handled according to the {@code nullIsLess} parameter.
- * Two {@code null} references are considered equal.
- *
- *
- * StringUtils.compare(null, null, *) = 0
- * StringUtils.compare(null , "a", true) < 0
- * StringUtils.compare(null , "a", false) > 0
- * StringUtils.compare("a", null, true) > 0
- * StringUtils.compare("a", null, false) < 0
- * StringUtils.compare("abc", "abc", *) = 0
- * StringUtils.compare("a", "b", *) < 0
- * StringUtils.compare("b", "a", *) > 0
- * StringUtils.compare("a", "B", *) > 0
- * StringUtils.compare("ab", "abc", *) < 0
- *
- *
- * @see String#compareTo(String)
- * @param str1 the String to compare from
- * @param str2 the String to compare to
- * @param nullIsLess whether consider {@code null} value less than non-{@code null} value
- * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
- * @since 3.5
- */
- public static int compare(final String str1, final String str2, final boolean nullIsLess) {
- if (str1 == str2) {
- return 0;
- }
- if (str1 == null) {
- return nullIsLess ? -1 : 1;
- }
- if (str2 == null) {
- return nullIsLess ? 1 : - 1;
- }
- return str1.compareTo(str2);
- }
-
- /**
- * Compare two Strings lexicographically, ignoring case differences,
- * as per {@link String#compareToIgnoreCase(String)}, returning :
- *
- * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
- * {@code int < 0}, if {@code str1} is less than {@code str2}
- * {@code int > 0}, if {@code str1} is greater than {@code str2}
- *
- *
- * This is a {@code null} safe version of :
- * str1.compareToIgnoreCase(str2)
- *
- * {@code null} value is considered less than non-{@code null} value.
- * Two {@code null} references are considered equal.
- * Comparison is case insensitive.
- *
- *
- * StringUtils.compareIgnoreCase(null, null) = 0
- * StringUtils.compareIgnoreCase(null , "a") < 0
- * StringUtils.compareIgnoreCase("a", null) > 0
- * StringUtils.compareIgnoreCase("abc", "abc") = 0
- * StringUtils.compareIgnoreCase("abc", "ABC") = 0
- * StringUtils.compareIgnoreCase("a", "b") < 0
- * StringUtils.compareIgnoreCase("b", "a") > 0
- * StringUtils.compareIgnoreCase("a", "B") < 0
- * StringUtils.compareIgnoreCase("A", "b") < 0
- * StringUtils.compareIgnoreCase("ab", "ABC") < 0
- *
- *
- * @see #compareIgnoreCase(String, String, boolean)
- * @see String#compareToIgnoreCase(String)
- * @param str1 the String to compare from
- * @param str2 the String to compare to
- * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
- * ignoring case differences.
- * @since 3.5
- */
- public static int compareIgnoreCase(final String str1, final String str2) {
- return compareIgnoreCase(str1, str2, true);
- }
-
- /**
- * Compare two Strings lexicographically, ignoring case differences,
- * as per {@link String#compareToIgnoreCase(String)}, returning :
- *
- * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
- * {@code int < 0}, if {@code str1} is less than {@code str2}
- * {@code int > 0}, if {@code str1} is greater than {@code str2}
- *
- *
- * This is a {@code null} safe version of :
- * str1.compareToIgnoreCase(str2)
- *
- * {@code null} inputs are handled according to the {@code nullIsLess} parameter.
- * Two {@code null} references are considered equal.
- * Comparison is case insensitive.
- *
- *
- * StringUtils.compareIgnoreCase(null, null, *) = 0
- * StringUtils.compareIgnoreCase(null , "a", true) < 0
- * StringUtils.compareIgnoreCase(null , "a", false) > 0
- * StringUtils.compareIgnoreCase("a", null, true) > 0
- * StringUtils.compareIgnoreCase("a", null, false) < 0
- * StringUtils.compareIgnoreCase("abc", "abc", *) = 0
- * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0
- * StringUtils.compareIgnoreCase("a", "b", *) < 0
- * StringUtils.compareIgnoreCase("b", "a", *) > 0
- * StringUtils.compareIgnoreCase("a", "B", *) < 0
- * StringUtils.compareIgnoreCase("A", "b", *) < 0
- * StringUtils.compareIgnoreCase("ab", "abc", *) < 0
- *
- *
- * @see String#compareToIgnoreCase(String)
- * @param str1 the String to compare from
- * @param str2 the String to compare to
- * @param nullIsLess whether consider {@code null} value less than non-{@code null} value
- * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
- * ignoring case differences.
- * @since 3.5
- */
- public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
- if (str1 == str2) {
- return 0;
- }
- if (str1 == null) {
- return nullIsLess ? -1 : 1;
- }
- if (str2 == null) {
- return nullIsLess ? 1 : - 1;
- }
- return str1.compareToIgnoreCase(str2);
- }
-
- /**
- * Compares given string to a CharSequences vararg of searchStrings,
- * returning {@code true} if the string is equal to any of the searchStrings.
- *
- *
- * StringUtils.equalsAny(null, (CharSequence[]) null) = false
- * StringUtils.equalsAny(null, null, null) = true
- * StringUtils.equalsAny(null, "abc", "def") = false
- * StringUtils.equalsAny("abc", null, "def") = false
- * StringUtils.equalsAny("abc", "abc", "def") = true
- * StringUtils.equalsAny("abc", "ABC", "DEF") = false
- *
- *
- * @param string to compare, may be {@code null}.
- * @param searchStrings a vararg of strings, may be {@code null}.
- * @return {@code true} if the string is equal (case-sensitive) to any other element of searchStrings;
- * {@code false} if searchStrings is null or contains no matches.
- * @since 3.5
- */
- public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
- if (ArrayUtils.isNotEmpty(searchStrings)) {
- for (final CharSequence next : searchStrings) {
- if (equals(string, next)) {
- return true;
- }
- }
- }
- return false;
- }
-
-
- /**
- * Compares given string to a CharSequences vararg of searchStrings,
- * returning {@code true} if the string is equal to any of the searchStrings, ignoring case.
- *
- *
- * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
- * StringUtils.equalsAnyIgnoreCase(null, null, null) = true
- * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false
- * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false
- * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
- * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
- *
- *
- * @param string to compare, may be {@code null}.
- * @param searchStrings a vararg of strings, may be {@code null}.
- * @return {@code true} if the string is equal (case-insensitive) to any other element of searchStrings;
- * {@code false} if searchStrings is null or contains no matches.
- * @since 3.5
- */
- public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) {
- if (ArrayUtils.isNotEmpty(searchStrings)) {
- for (final CharSequence next : searchStrings) {
- if (equalsIgnoreCase(string, next)) {
- return true;
- }
- }
- }
- return false;
- }
-
- // IndexOf
- //-----------------------------------------------------------------------
- /**
- * Returns the index within seq of the first occurrence of
- * the specified character. If a character with value
- * searchChar occurs in the character sequence represented by
- * seq CharSequence object, then the index (in Unicode
- * code units) of the first such occurrence is returned. For
- * values of searchChar in the range from 0 to 0xFFFF
- * (inclusive), this is the smallest value k such that:
- *
- * this.charAt(k ) == searchChar
- *
- * is true. For other values of searchChar, it is the
- * smallest value k such that:
- *
- * this.codePointAt(k ) == searchChar
- *
- * is true. In either case, if no such character occurs in seq,
- * then {@code INDEX_NOT_FOUND (-1)} is returned.
- *
- * Furthermore, a {@code null} or empty ("") CharSequence will
- * return {@code INDEX_NOT_FOUND (-1)}.
- *
- *
- * StringUtils.indexOf(null, *) = -1
- * StringUtils.indexOf("", *) = -1
- * StringUtils.indexOf("aabaabaa", 'a') = 0
- * StringUtils.indexOf("aabaabaa", 'b') = 2
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChar the character to find
- * @return the first index of the search character,
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
- */
- public static int indexOf(final CharSequence seq, final int searchChar) {
- if (isEmpty(seq)) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.indexOf(seq, searchChar, 0);
- }
-
- /**
- *
- * Returns the index within seq of the first occurrence of the
- * specified character, starting the search at the specified index.
- *
- * If a character with value searchChar occurs in the
- * character sequence represented by the seq CharSequence
- * object at an index no smaller than startPos, then
- * the index of the first such occurrence is returned. For values
- * of searchChar in the range from 0 to 0xFFFF (inclusive),
- * this is the smallest value k such that:
- *
- * (this.charAt(k ) == searchChar) && (k >= startPos)
- *
- * is true. For other values of searchChar, it is the
- * smallest value k such that:
- *
- * (this.codePointAt(k ) == searchChar) && (k >= startPos)
- *
- * is true. In either case, if no such character occurs in seq
- * at or after position startPos, then
- * -1 is returned.
- *
- *
- * There is no restriction on the value of startPos. If it
- * is negative, it has the same effect as if it were zero: this entire
- * string may be searched. If it is greater than the length of this
- * string, it has the same effect as if it were equal to the length of
- * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a
- * {@code null} or empty ("") CharSequence will
- * return {@code (INDEX_NOT_FOUND) -1}.
- *
- *
All indices are specified in char values
- * (Unicode code units).
- *
- *
- * StringUtils.indexOf(null, *, *) = -1
- * StringUtils.indexOf("", *, *) = -1
- * StringUtils.indexOf("aabaabaa", 'b', 0) = 2
- * StringUtils.indexOf("aabaabaa", 'b', 3) = 5
- * StringUtils.indexOf("aabaabaa", 'b', 9) = -1
- * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChar the character to find
- * @param startPos the start position, negative treated as zero
- * @return the first index of the search character (always ≥ startPos),
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
- */
- public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
- if (isEmpty(seq)) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.indexOf(seq, searchChar, startPos);
- }
-
- /**
- * Finds the first index within a CharSequence, handling {@code null}.
- * This method uses {@link String#indexOf(String, int)} if possible.
- *
- * A {@code null} CharSequence will return {@code -1}.
- *
- *
- * StringUtils.indexOf(null, *) = -1
- * StringUtils.indexOf(*, null) = -1
- * StringUtils.indexOf("", "") = 0
- * StringUtils.indexOf("", *) = -1 (except when * = "")
- * StringUtils.indexOf("aabaabaa", "a") = 0
- * StringUtils.indexOf("aabaabaa", "b") = 2
- * StringUtils.indexOf("aabaabaa", "ab") = 1
- * StringUtils.indexOf("aabaabaa", "") = 0
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchSeq the CharSequence to find, may be null
- * @return the first index of the search CharSequence,
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
- */
- public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
- if (seq == null || searchSeq == null) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.indexOf(seq, searchSeq, 0);
- }
-
- /**
- * Finds the first index within a CharSequence, handling {@code null}.
- * This method uses {@link String#indexOf(String, int)} if possible.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position is treated as zero.
- * An empty ("") search CharSequence always matches.
- * A start position greater than the string length only matches
- * an empty search CharSequence.
- *
- *
- * StringUtils.indexOf(null, *, *) = -1
- * StringUtils.indexOf(*, null, *) = -1
- * StringUtils.indexOf("", "", 0) = 0
- * StringUtils.indexOf("", *, 0) = -1 (except when * = "")
- * StringUtils.indexOf("aabaabaa", "a", 0) = 0
- * StringUtils.indexOf("aabaabaa", "b", 0) = 2
- * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
- * StringUtils.indexOf("aabaabaa", "b", 3) = 5
- * StringUtils.indexOf("aabaabaa", "b", 9) = -1
- * StringUtils.indexOf("aabaabaa", "b", -1) = 2
- * StringUtils.indexOf("aabaabaa", "", 2) = 2
- * StringUtils.indexOf("abc", "", 9) = 3
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchSeq the CharSequence to find, may be null
- * @param startPos the start position, negative treated as zero
- * @return the first index of the search CharSequence (always ≥ startPos),
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
- */
- public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
- if (seq == null || searchSeq == null) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.indexOf(seq, searchSeq, startPos);
- }
-
- /**
- * Finds the n-th index within a CharSequence, handling {@code null}.
- * This method uses {@link String#indexOf(String)} if possible.
- * Note: The code starts looking for a match at the start of the target,
- * incrementing the starting index by one after each successful match
- * (unless {@code searchStr} is an empty string in which case the position
- * is never incremented and {@code 0} is returned immediately).
- * This means that matches may overlap.
- * A {@code null} CharSequence will return {@code -1}.
- *
- *
- * StringUtils.ordinalIndexOf(null, *, *) = -1
- * StringUtils.ordinalIndexOf(*, null, *) = -1
- * StringUtils.ordinalIndexOf("", "", *) = 0
- * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
- * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
- * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
- * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
- * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
- * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
- * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
- * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
- *
- *
- * Matches may overlap:
- *
- * StringUtils.ordinalIndexOf("ababab","aba", 1) = 0
- * StringUtils.ordinalIndexOf("ababab","aba", 2) = 2
- * StringUtils.ordinalIndexOf("ababab","aba", 3) = -1
- *
- * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
- * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
- * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
- * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
- *
- *
- * Note that 'head(CharSequence str, int n)' may be implemented as:
- *
- *
- * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @param ordinal the n-th {@code searchStr} to find
- * @return the n-th index of the search CharSequence,
- * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
- * @since 2.1
- * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
- */
- public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
- return ordinalIndexOf(str, searchStr, ordinal, false);
- }
-
- /**
- * Finds the n-th index within a String, handling {@code null}.
- * This method uses {@link String#indexOf(String)} if possible.
- * Note that matches may overlap
- *
- *
A {@code null} CharSequence will return {@code -1}.
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed.
- * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
- * @return the n-th index of the search CharSequence,
- * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
- */
- // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
- private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
- if (str == null || searchStr == null || ordinal <= 0) {
- return INDEX_NOT_FOUND;
- }
- if (searchStr.length() == 0) {
- return lastIndex ? str.length() : 0;
- }
- int found = 0;
- // set the initial index beyond the end of the string
- // this is to allow for the initial index decrement/increment
- int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
- do {
- if (lastIndex) {
- index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string
- } else {
- index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
- }
- if (index < 0) {
- return index;
- }
- found++;
- } while (found < ordinal);
- return index;
- }
-
- /**
- * Case in-sensitive find of the first index within a CharSequence.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position is treated as zero.
- * An empty ("") search CharSequence always matches.
- * A start position greater than the string length only matches
- * an empty search CharSequence.
- *
- *
- * StringUtils.indexOfIgnoreCase(null, *) = -1
- * StringUtils.indexOfIgnoreCase(*, null) = -1
- * StringUtils.indexOfIgnoreCase("", "") = 0
- * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0
- * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2
- * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @return the first index of the search CharSequence,
- * -1 if no match or {@code null} string input
- * @since 2.5
- * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
- */
- public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
- return indexOfIgnoreCase(str, searchStr, 0);
- }
-
- /**
- * Case in-sensitive find of the first index within a CharSequence
- * from the specified position.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position is treated as zero.
- * An empty ("") search CharSequence always matches.
- * A start position greater than the string length only matches
- * an empty search CharSequence.
- *
- *
- * StringUtils.indexOfIgnoreCase(null, *, *) = -1
- * StringUtils.indexOfIgnoreCase(*, null, *) = -1
- * StringUtils.indexOfIgnoreCase("", "", 0) = 0
- * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0
- * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2
- * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
- * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5
- * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1
- * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
- * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2
- * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @param startPos the start position, negative treated as zero
- * @return the first index of the search CharSequence (always ≥ startPos),
- * -1 if no match or {@code null} string input
- * @since 2.5
- * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
- */
- public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
- if (str == null || searchStr == null) {
- return INDEX_NOT_FOUND;
- }
- if (startPos < 0) {
- startPos = 0;
- }
- final int endLimit = str.length() - searchStr.length() + 1;
- if (startPos > endLimit) {
- return INDEX_NOT_FOUND;
- }
- if (searchStr.length() == 0) {
- return startPos;
- }
- for (int i = startPos; i < endLimit; i++) {
- if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- // LastIndexOf
- //-----------------------------------------------------------------------
- /**
- * Returns the index within seq of the last occurrence of
- * the specified character. For values of searchChar in the
- * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
- * units) returned is the largest value k such that:
- *
- * this.charAt(k ) == searchChar
- *
- * is true. For other values of searchChar, it is the
- * largest value k such that:
- *
- * this.codePointAt(k ) == searchChar
- *
- * is true. In either case, if no such character occurs in this
- * string, then -1 is returned. Furthermore, a {@code null} or empty ("")
- * CharSequence will return {@code -1}. The
- * seq CharSequence object is searched backwards
- * starting at the last character.
- *
- *
- * StringUtils.lastIndexOf(null, *) = -1
- * StringUtils.lastIndexOf("", *) = -1
- * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
- * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChar the character to find
- * @return the last index of the search character,
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
- */
- public static int lastIndexOf(final CharSequence seq, final int searchChar) {
- if (isEmpty(seq)) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
- }
-
- /**
- * Returns the index within seq of the last occurrence of
- * the specified character, searching backward starting at the
- * specified index. For values of searchChar in the range
- * from 0 to 0xFFFF (inclusive), the index returned is the largest
- * value k such that:
- *
- * (this.charAt(k ) == searchChar) && (k <= startPos)
- *
- * is true. For other values of searchChar, it is the
- * largest value k such that:
- *
- * (this.codePointAt(k ) == searchChar) && (k <= startPos)
- *
- * is true. In either case, if no such character occurs in seq
- * at or before position startPos, then
- * -1 is returned. Furthermore, a {@code null} or empty ("")
- * CharSequence will return {@code -1}. A start position greater
- * than the string length searches the whole string.
- * The search starts at the startPos and works backwards;
- * matches starting after the start position are ignored.
- *
- * All indices are specified in char values
- * (Unicode code units).
- *
- *
- * StringUtils.lastIndexOf(null, *, *) = -1
- * StringUtils.lastIndexOf("", *, *) = -1
- * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5
- * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2
- * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1
- * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5
- * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
- * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChar the character to find
- * @param startPos the start position
- * @return the last index of the search character (always ≤ startPos),
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
- */
- public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
- if (isEmpty(seq)) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
- }
-
- /**
- * Finds the last index within a CharSequence, handling {@code null}.
- * This method uses {@link String#lastIndexOf(String)} if possible.
- *
- * A {@code null} CharSequence will return {@code -1}.
- *
- *
- * StringUtils.lastIndexOf(null, *) = -1
- * StringUtils.lastIndexOf(*, null) = -1
- * StringUtils.lastIndexOf("", "") = 0
- * StringUtils.lastIndexOf("aabaabaa", "a") = 7
- * StringUtils.lastIndexOf("aabaabaa", "b") = 5
- * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
- * StringUtils.lastIndexOf("aabaabaa", "") = 8
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchSeq the CharSequence to find, may be null
- * @return the last index of the search String,
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
- */
- public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
- if (seq == null || searchSeq == null) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());
- }
-
- /**
- * Finds the n-th last index within a String, handling {@code null}.
- * This method uses {@link String#lastIndexOf(String)}.
- *
- * A {@code null} String will return {@code -1}.
- *
- *
- * StringUtils.lastOrdinalIndexOf(null, *, *) = -1
- * StringUtils.lastOrdinalIndexOf(*, null, *) = -1
- * StringUtils.lastOrdinalIndexOf("", "", *) = 0
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8
- * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8
- *
- *
- * Note that 'tail(CharSequence str, int n)' may be implemented as:
- *
- *
- * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @param ordinal the n-th last {@code searchStr} to find
- * @return the n-th last index of the search CharSequence,
- * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
- * @since 2.5
- * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
- */
- public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
- return ordinalIndexOf(str, searchStr, ordinal, true);
- }
-
- /**
- * Finds the last index within a CharSequence, handling {@code null}.
- * This method uses {@link String#lastIndexOf(String, int)} if possible.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position returns {@code -1}.
- * An empty ("") search CharSequence always matches unless the start position is negative.
- * A start position greater than the string length searches the whole string.
- * The search starts at the startPos and works backwards; matches starting after the start
- * position are ignored.
- *
- *
- *
- * StringUtils.lastIndexOf(null, *, *) = -1
- * StringUtils.lastIndexOf(*, null, *) = -1
- * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7
- * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5
- * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
- * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5
- * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
- * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
- * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
- * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1
- * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2
- * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchSeq the CharSequence to find, may be null
- * @param startPos the start position, negative treated as zero
- * @return the last index of the search CharSequence (always ≤ startPos),
- * -1 if no match or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
- */
- public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
- if (seq == null || searchSeq == null) {
- return INDEX_NOT_FOUND;
- }
- return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);
- }
-
- /**
- * Case in-sensitive find of the last index within a CharSequence.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position returns {@code -1}.
- * An empty ("") search CharSequence always matches unless the start position is negative.
- * A start position greater than the string length searches the whole string.
- *
- *
- * StringUtils.lastIndexOfIgnoreCase(null, *) = -1
- * StringUtils.lastIndexOfIgnoreCase(*, null) = -1
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @return the first index of the search CharSequence,
- * -1 if no match or {@code null} string input
- * @since 2.5
- * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
- */
- public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
- if (str == null || searchStr == null) {
- return INDEX_NOT_FOUND;
- }
- return lastIndexOfIgnoreCase(str, searchStr, str.length());
- }
-
- /**
- * Case in-sensitive find of the last index within a CharSequence
- * from the specified position.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A negative start position returns {@code -1}.
- * An empty ("") search CharSequence always matches unless the start position is negative.
- * A start position greater than the string length searches the whole string.
- * The search starts at the startPos and works backwards; matches starting after the start
- * position are ignored.
- *
- *
- *
- * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1
- * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0
- * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @param startPos the start position
- * @return the last index of the search CharSequence (always ≤ startPos),
- * -1 if no match or {@code null} input
- * @since 2.5
- * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
- */
- public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
- if (str == null || searchStr == null) {
- return INDEX_NOT_FOUND;
- }
- if (startPos > str.length() - searchStr.length()) {
- startPos = str.length() - searchStr.length();
- }
- if (startPos < 0) {
- return INDEX_NOT_FOUND;
- }
- if (searchStr.length() == 0) {
- return startPos;
- }
-
- for (int i = startPos; i >= 0; i--) {
- if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
- return i;
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- // Contains
- //-----------------------------------------------------------------------
- /**
- * Checks if CharSequence contains a search character, handling {@code null}.
- * This method uses {@link String#indexOf(int)} if possible.
- *
- * A {@code null} or empty ("") CharSequence will return {@code false}.
- *
- *
- * StringUtils.contains(null, *) = false
- * StringUtils.contains("", *) = false
- * StringUtils.contains("abc", 'a') = true
- * StringUtils.contains("abc", 'z') = false
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChar the character to find
- * @return true if the CharSequence contains the search character,
- * false if not or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
- */
- public static boolean contains(final CharSequence seq, final int searchChar) {
- if (isEmpty(seq)) {
- return false;
- }
- return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
- }
-
- /**
- * Checks if CharSequence contains a search CharSequence, handling {@code null}.
- * This method uses {@link String#indexOf(String)} if possible.
- *
- * A {@code null} CharSequence will return {@code false}.
- *
- *
- * StringUtils.contains(null, *) = false
- * StringUtils.contains(*, null) = false
- * StringUtils.contains("", "") = true
- * StringUtils.contains("abc", "") = true
- * StringUtils.contains("abc", "a") = true
- * StringUtils.contains("abc", "z") = false
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchSeq the CharSequence to find, may be null
- * @return true if the CharSequence contains the search CharSequence,
- * false if not or {@code null} string input
- * @since 2.0
- * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
- */
- public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
- if (seq == null || searchSeq == null) {
- return false;
- }
- return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;
- }
-
- /**
- * Checks if CharSequence contains a search CharSequence irrespective of case,
- * handling {@code null}. Case-insensitivity is defined as by
- * {@link String#equalsIgnoreCase(String)}.
- *
- *
A {@code null} CharSequence will return {@code false}.
- *
- *
- * StringUtils.containsIgnoreCase(null, *) = false
- * StringUtils.containsIgnoreCase(*, null) = false
- * StringUtils.containsIgnoreCase("", "") = true
- * StringUtils.containsIgnoreCase("abc", "") = true
- * StringUtils.containsIgnoreCase("abc", "a") = true
- * StringUtils.containsIgnoreCase("abc", "z") = false
- * StringUtils.containsIgnoreCase("abc", "A") = true
- * StringUtils.containsIgnoreCase("abc", "Z") = false
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStr the CharSequence to find, may be null
- * @return true if the CharSequence contains the search CharSequence irrespective of
- * case or false if not or {@code null} string input
- * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
- */
- public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
- if (str == null || searchStr == null) {
- return false;
- }
- final int len = searchStr.length();
- final int max = str.length() - len;
- for (int i = 0; i <= max; i++) {
- if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check whether the given CharSequence contains any whitespace characters.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * @param seq the CharSequence to check (may be {@code null})
- * @return {@code true} if the CharSequence is not empty and
- * contains at least 1 (breaking) whitespace character
- * @since 3.0
- */
- // From org.springframework.util.StringUtils, under Apache License 2.0
- public static boolean containsWhitespace(final CharSequence seq) {
- if (isEmpty(seq)) {
- return false;
- }
- final int strLen = seq.length();
- for (int i = 0; i < strLen; i++) {
- if (Character.isWhitespace(seq.charAt(i))) {
- return true;
- }
- }
- return false;
- }
-
- // IndexOfAny chars
- //-----------------------------------------------------------------------
- /**
- * Search a CharSequence to find the first index of any
- * character in the given set of characters.
- *
- * A {@code null} String will return {@code -1}.
- * A {@code null} or zero length search array will return {@code -1}.
- *
- *
- * StringUtils.indexOfAny(null, *) = -1
- * StringUtils.indexOfAny("", *) = -1
- * StringUtils.indexOfAny(*, null) = -1
- * StringUtils.indexOfAny(*, []) = -1
- * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
- * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
- * StringUtils.indexOfAny("aba", ['z']) = -1
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param searchChars the chars to search for, may be null
- * @return the index of any of the chars, -1 if no match or null input
- * @since 2.0
- * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
- */
- public static int indexOfAny(final CharSequence cs, final char... searchChars) {
- if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
- return INDEX_NOT_FOUND;
- }
- final int csLen = cs.length();
- final int csLast = csLen - 1;
- final int searchLen = searchChars.length;
- final int searchLast = searchLen - 1;
- for (int i = 0; i < csLen; i++) {
- final char ch = cs.charAt(i);
- for (int j = 0; j < searchLen; j++) {
- if (searchChars[j] == ch) {
- if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
- // ch is a supplementary character
- if (searchChars[j + 1] == cs.charAt(i + 1)) {
- return i;
- }
- } else {
- return i;
- }
- }
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- * Search a CharSequence to find the first index of any
- * character in the given set of characters.
- *
- * A {@code null} String will return {@code -1}.
- * A {@code null} search string will return {@code -1}.
- *
- *
- * StringUtils.indexOfAny(null, *) = -1
- * StringUtils.indexOfAny("", *) = -1
- * StringUtils.indexOfAny(*, null) = -1
- * StringUtils.indexOfAny(*, "") = -1
- * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
- * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
- * StringUtils.indexOfAny("aba","z") = -1
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param searchChars the chars to search for, may be null
- * @return the index of any of the chars, -1 if no match or null input
- * @since 2.0
- * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
- */
- public static int indexOfAny(final CharSequence cs, final String searchChars) {
- if (isEmpty(cs) || isEmpty(searchChars)) {
- return INDEX_NOT_FOUND;
- }
- return indexOfAny(cs, searchChars.toCharArray());
- }
-
- // ContainsAny
- //-----------------------------------------------------------------------
- /**
- * Checks if the CharSequence contains any character in the given
- * set of characters.
- *
- * A {@code null} CharSequence will return {@code false}.
- * A {@code null} or zero length search array will return {@code false}.
- *
- *
- * StringUtils.containsAny(null, *) = false
- * StringUtils.containsAny("", *) = false
- * StringUtils.containsAny(*, null) = false
- * StringUtils.containsAny(*, []) = false
- * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
- * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
- * StringUtils.containsAny("zzabyycdxx",['z','y']) = true
- * StringUtils.containsAny("aba", ['z']) = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param searchChars the chars to search for, may be null
- * @return the {@code true} if any of the chars are found,
- * {@code false} if no match or null input
- * @since 2.4
- * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
- */
- public static boolean containsAny(final CharSequence cs, final char... searchChars) {
- if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
- return false;
- }
- final int csLength = cs.length();
- final int searchLength = searchChars.length;
- final int csLast = csLength - 1;
- final int searchLast = searchLength - 1;
- for (int i = 0; i < csLength; i++) {
- final char ch = cs.charAt(i);
- for (int j = 0; j < searchLength; j++) {
- if (searchChars[j] == ch) {
- if (Character.isHighSurrogate(ch)) {
- if (j == searchLast) {
- // missing low surrogate, fine, like String.indexOf(String)
- return true;
- }
- if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
- return true;
- }
- } else {
- // ch is in the Basic Multilingual Plane
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- *
- * Checks if the CharSequence contains any character in the given set of characters.
- *
- *
- *
- * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
- * {@code false}.
- *
- *
- *
- * StringUtils.containsAny(null, *) = false
- * StringUtils.containsAny("", *) = false
- * StringUtils.containsAny(*, null) = false
- * StringUtils.containsAny(*, "") = false
- * StringUtils.containsAny("zzabyycdxx", "za") = true
- * StringUtils.containsAny("zzabyycdxx", "by") = true
- * StringUtils.containsAny("zzabyycdxx", "zy") = true
- * StringUtils.containsAny("zzabyycdxx", "\tx") = true
- * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
- * StringUtils.containsAny("aba","z") = false
- *
- *
- * @param cs
- * the CharSequence to check, may be null
- * @param searchChars
- * the chars to search for, may be null
- * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
- * @since 2.4
- * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
- */
- public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
- if (searchChars == null) {
- return false;
- }
- return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
- }
-
- /**
- * Checks if the CharSequence contains any of the CharSequences in the given array.
- *
- *
- * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero
- * length search array will return {@code false}.
- *
- *
- *
- * StringUtils.containsAny(null, *) = false
- * StringUtils.containsAny("", *) = false
- * StringUtils.containsAny(*, null) = false
- * StringUtils.containsAny(*, []) = false
- * StringUtils.containsAny("abcd", "ab", null) = true
- * StringUtils.containsAny("abcd", "ab", "cd") = true
- * StringUtils.containsAny("abc", "d", "abc") = true
- *
- *
- *
- * @param cs The CharSequence to check, may be null
- * @param searchCharSequences The array of CharSequences to search for, may be null.
- * Individual CharSequences may be null as well.
- * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
- * @since 3.4
- */
- public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
- if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {
- return false;
- }
- for (final CharSequence searchCharSequence : searchCharSequences) {
- if (contains(cs, searchCharSequence)) {
- return true;
- }
- }
- return false;
- }
-
- // IndexOfAnyBut chars
- //-----------------------------------------------------------------------
- /**
- * Searches a CharSequence to find the first index of any
- * character not in the given set of characters.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A {@code null} or zero length search array will return {@code -1}.
- *
- *
- * StringUtils.indexOfAnyBut(null, *) = -1
- * StringUtils.indexOfAnyBut("", *) = -1
- * StringUtils.indexOfAnyBut(*, null) = -1
- * StringUtils.indexOfAnyBut(*, []) = -1
- * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
- * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0
- * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1
-
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param searchChars the chars to search for, may be null
- * @return the index of any of the chars, -1 if no match or null input
- * @since 2.0
- * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
- */
- public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
- if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
- return INDEX_NOT_FOUND;
- }
- final int csLen = cs.length();
- final int csLast = csLen - 1;
- final int searchLen = searchChars.length;
- final int searchLast = searchLen - 1;
- outer:
- for (int i = 0; i < csLen; i++) {
- final char ch = cs.charAt(i);
- for (int j = 0; j < searchLen; j++) {
- if (searchChars[j] == ch) {
- if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
- if (searchChars[j + 1] == cs.charAt(i + 1)) {
- continue outer;
- }
- } else {
- continue outer;
- }
- }
- }
- return i;
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- * Search a CharSequence to find the first index of any
- * character not in the given set of characters.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A {@code null} or empty search string will return {@code -1}.
- *
- *
- * StringUtils.indexOfAnyBut(null, *) = -1
- * StringUtils.indexOfAnyBut("", *) = -1
- * StringUtils.indexOfAnyBut(*, null) = -1
- * StringUtils.indexOfAnyBut(*, "") = -1
- * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
- * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1
- * StringUtils.indexOfAnyBut("aba","ab") = -1
- *
- *
- * @param seq the CharSequence to check, may be null
- * @param searchChars the chars to search for, may be null
- * @return the index of any of the chars, -1 if no match or null input
- * @since 2.0
- * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
- */
- public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
- if (isEmpty(seq) || isEmpty(searchChars)) {
- return INDEX_NOT_FOUND;
- }
- final int strLen = seq.length();
- for (int i = 0; i < strLen; i++) {
- final char ch = seq.charAt(i);
- final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;
- if (i + 1 < strLen && Character.isHighSurrogate(ch)) {
- final char ch2 = seq.charAt(i + 1);
- if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {
- return i;
- }
- } else {
- if (!chFound) {
- return i;
- }
- }
- }
- return INDEX_NOT_FOUND;
- }
-
- // ContainsOnly
- //-----------------------------------------------------------------------
- /**
- * Checks if the CharSequence contains only certain characters.
- *
- * A {@code null} CharSequence will return {@code false}.
- * A {@code null} valid character array will return {@code false}.
- * An empty CharSequence (length()=0) always returns {@code true}.
- *
- *
- * StringUtils.containsOnly(null, *) = false
- * StringUtils.containsOnly(*, null) = false
- * StringUtils.containsOnly("", *) = true
- * StringUtils.containsOnly("ab", '') = false
- * StringUtils.containsOnly("abab", 'abc') = true
- * StringUtils.containsOnly("ab1", 'abc') = false
- * StringUtils.containsOnly("abz", 'abc') = false
- *
- *
- * @param cs the String to check, may be null
- * @param valid an array of valid chars, may be null
- * @return true if it only contains valid chars and is non-null
- * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
- */
- public static boolean containsOnly(final CharSequence cs, final char... valid) {
- // All these pre-checks are to maintain API with an older version
- if (valid == null || cs == null) {
- return false;
- }
- if (cs.length() == 0) {
- return true;
- }
- if (valid.length == 0) {
- return false;
- }
- return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
- }
-
- /**
- * Checks if the CharSequence contains only certain characters.
- *
- * A {@code null} CharSequence will return {@code false}.
- * A {@code null} valid character String will return {@code false}.
- * An empty String (length()=0) always returns {@code true}.
- *
- *
- * StringUtils.containsOnly(null, *) = false
- * StringUtils.containsOnly(*, null) = false
- * StringUtils.containsOnly("", *) = true
- * StringUtils.containsOnly("ab", "") = false
- * StringUtils.containsOnly("abab", "abc") = true
- * StringUtils.containsOnly("ab1", "abc") = false
- * StringUtils.containsOnly("abz", "abc") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param validChars a String of valid chars, may be null
- * @return true if it only contains valid chars and is non-null
- * @since 2.0
- * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
- */
- public static boolean containsOnly(final CharSequence cs, final String validChars) {
- if (cs == null || validChars == null) {
- return false;
- }
- return containsOnly(cs, validChars.toCharArray());
- }
-
- // ContainsNone
- //-----------------------------------------------------------------------
- /**
- * Checks that the CharSequence does not contain certain characters.
- *
- * A {@code null} CharSequence will return {@code true}.
- * A {@code null} invalid character array will return {@code true}.
- * An empty CharSequence (length()=0) always returns true.
- *
- *
- * StringUtils.containsNone(null, *) = true
- * StringUtils.containsNone(*, null) = true
- * StringUtils.containsNone("", *) = true
- * StringUtils.containsNone("ab", '') = true
- * StringUtils.containsNone("abab", 'xyz') = true
- * StringUtils.containsNone("ab1", 'xyz') = true
- * StringUtils.containsNone("abz", 'xyz') = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param searchChars an array of invalid chars, may be null
- * @return true if it contains none of the invalid chars, or is null
- * @since 2.0
- * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
- */
- public static boolean containsNone(final CharSequence cs, final char... searchChars) {
- if (cs == null || searchChars == null) {
- return true;
- }
- final int csLen = cs.length();
- final int csLast = csLen - 1;
- final int searchLen = searchChars.length;
- final int searchLast = searchLen - 1;
- for (int i = 0; i < csLen; i++) {
- final char ch = cs.charAt(i);
- for (int j = 0; j < searchLen; j++) {
- if (searchChars[j] == ch) {
- if (Character.isHighSurrogate(ch)) {
- if (j == searchLast) {
- // missing low surrogate, fine, like String.indexOf(String)
- return false;
- }
- if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
- return false;
- }
- } else {
- // ch is in the Basic Multilingual Plane
- return false;
- }
- }
- }
- }
- return true;
- }
-
- /**
- * Checks that the CharSequence does not contain certain characters.
- *
- * A {@code null} CharSequence will return {@code true}.
- * A {@code null} invalid character array will return {@code true}.
- * An empty String ("") always returns true.
- *
- *
- * StringUtils.containsNone(null, *) = true
- * StringUtils.containsNone(*, null) = true
- * StringUtils.containsNone("", *) = true
- * StringUtils.containsNone("ab", "") = true
- * StringUtils.containsNone("abab", "xyz") = true
- * StringUtils.containsNone("ab1", "xyz") = true
- * StringUtils.containsNone("abz", "xyz") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @param invalidChars a String of invalid chars, may be null
- * @return true if it contains none of the invalid chars, or is null
- * @since 2.0
- * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
- */
- public static boolean containsNone(final CharSequence cs, final String invalidChars) {
- if (cs == null || invalidChars == null) {
- return true;
- }
- return containsNone(cs, invalidChars.toCharArray());
- }
-
- // IndexOfAny strings
- //-----------------------------------------------------------------------
- /**
- * Find the first index of any of a set of potential substrings.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A {@code null} or zero length search array will return {@code -1}.
- * A {@code null} search array entry will be ignored, but a search
- * array containing "" will return {@code 0} if {@code str} is not
- * null. This method uses {@link String#indexOf(String)} if possible.
- *
- *
- * StringUtils.indexOfAny(null, *) = -1
- * StringUtils.indexOfAny(*, null) = -1
- * StringUtils.indexOfAny(*, []) = -1
- * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2
- * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2
- * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"]) = -1
- * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
- * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0
- * StringUtils.indexOfAny("", [""]) = 0
- * StringUtils.indexOfAny("", ["a"]) = -1
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStrs the CharSequences to search for, may be null
- * @return the first index of any of the searchStrs in str, -1 if no match
- * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
- */
- public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
- if (str == null || searchStrs == null) {
- return INDEX_NOT_FOUND;
- }
-
- // String's can't have a MAX_VALUEth index.
- int ret = Integer.MAX_VALUE;
-
- int tmp = 0;
- for (final CharSequence search : searchStrs) {
- if (search == null) {
- continue;
- }
- tmp = CharSequenceUtils.indexOf(str, search, 0);
- if (tmp == INDEX_NOT_FOUND) {
- continue;
- }
-
- if (tmp < ret) {
- ret = tmp;
- }
- }
-
- return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
- }
-
- /**
- * Find the latest index of any of a set of potential substrings.
- *
- * A {@code null} CharSequence will return {@code -1}.
- * A {@code null} search array will return {@code -1}.
- * A {@code null} or zero length search array entry will be ignored,
- * but a search array containing "" will return the length of {@code str}
- * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible
- *
- *
- * StringUtils.lastIndexOfAny(null, *) = -1
- * StringUtils.lastIndexOfAny(*, null) = -1
- * StringUtils.lastIndexOfAny(*, []) = -1
- * StringUtils.lastIndexOfAny(*, [null]) = -1
- * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
- * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
- * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
- * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
- * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10
- *
- *
- * @param str the CharSequence to check, may be null
- * @param searchStrs the CharSequences to search for, may be null
- * @return the last index of any of the CharSequences, -1 if no match
- * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
- */
- public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
- if (str == null || searchStrs == null) {
- return INDEX_NOT_FOUND;
- }
- int ret = INDEX_NOT_FOUND;
- int tmp = 0;
- for (final CharSequence search : searchStrs) {
- if (search == null) {
- continue;
- }
- tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
- if (tmp > ret) {
- ret = tmp;
- }
- }
- return ret;
- }
-
- // Substring
- //-----------------------------------------------------------------------
- /**
- * Gets a substring from the specified String avoiding exceptions.
- *
- * A negative start position can be used to start {@code n}
- * characters from the end of the String.
- *
- * A {@code null} String will return {@code null}.
- * An empty ("") String will return "".
- *
- *
- * StringUtils.substring(null, *) = null
- * StringUtils.substring("", *) = ""
- * StringUtils.substring("abc", 0) = "abc"
- * StringUtils.substring("abc", 2) = "c"
- * StringUtils.substring("abc", 4) = ""
- * StringUtils.substring("abc", -2) = "bc"
- * StringUtils.substring("abc", -4) = "abc"
- *
- *
- * @param str the String to get the substring from, may be null
- * @param start the position to start from, negative means
- * count back from the end of the String by this many characters
- * @return substring from start position, {@code null} if null String input
- */
- public static String substring(final String str, int start) {
- if (str == null) {
- return null;
- }
-
- // handle negatives, which means last n characters
- if (start < 0) {
- start = str.length() + start; // remember start is negative
- }
-
- if (start < 0) {
- start = 0;
- }
- if (start > str.length()) {
- return EMPTY;
- }
-
- return str.substring(start);
- }
-
- /**
- * Gets a substring from the specified String avoiding exceptions.
- *
- * A negative start position can be used to start/end {@code n}
- * characters from the end of the String.
- *
- * The returned substring starts with the character in the {@code start}
- * position and ends before the {@code end} position. All position counting is
- * zero-based -- i.e., to start at the beginning of the string use
- * {@code start = 0}. Negative start and end positions can be used to
- * specify offsets relative to the end of the String.
- *
- * If {@code start} is not strictly to the left of {@code end}, ""
- * is returned.
- *
- *
- * StringUtils.substring(null, *, *) = null
- * StringUtils.substring("", * , *) = "";
- * StringUtils.substring("abc", 0, 2) = "ab"
- * StringUtils.substring("abc", 2, 0) = ""
- * StringUtils.substring("abc", 2, 4) = "c"
- * StringUtils.substring("abc", 4, 6) = ""
- * StringUtils.substring("abc", 2, 2) = ""
- * StringUtils.substring("abc", -2, -1) = "b"
- * StringUtils.substring("abc", -4, 2) = "ab"
- *
- *
- * @param str the String to get the substring from, may be null
- * @param start the position to start from, negative means
- * count back from the end of the String by this many characters
- * @param end the position to end at (exclusive), negative means
- * count back from the end of the String by this many characters
- * @return substring from start position to end position,
- * {@code null} if null String input
- */
- public static String substring(final String str, int start, int end) {
- if (str == null) {
- return null;
- }
-
- // handle negatives
- if (end < 0) {
- end = str.length() + end; // remember end is negative
- }
- if (start < 0) {
- start = str.length() + start; // remember start is negative
- }
-
- // check length next
- if (end > str.length()) {
- end = str.length();
- }
-
- // if start is greater than end, return ""
- if (start > end) {
- return EMPTY;
- }
-
- if (start < 0) {
- start = 0;
- }
- if (end < 0) {
- end = 0;
- }
-
- return str.substring(start, end);
- }
-
- // Left/Right/Mid
- //-----------------------------------------------------------------------
- /**
- * Gets the leftmost {@code len} characters of a String.
- *
- * If {@code len} characters are not available, or the
- * String is {@code null}, the String will be returned without
- * an exception. An empty String is returned if len is negative.
- *
- *
- * StringUtils.left(null, *) = null
- * StringUtils.left(*, -ve) = ""
- * StringUtils.left("", *) = ""
- * StringUtils.left("abc", 0) = ""
- * StringUtils.left("abc", 2) = "ab"
- * StringUtils.left("abc", 4) = "abc"
- *
- *
- * @param str the String to get the leftmost characters from, may be null
- * @param len the length of the required String
- * @return the leftmost characters, {@code null} if null String input
- */
- public static String left(final String str, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0) {
- return EMPTY;
- }
- if (str.length() <= len) {
- return str;
- }
- return str.substring(0, len);
- }
-
- /**
- * Gets the rightmost {@code len} characters of a String.
- *
- * If {@code len} characters are not available, or the String
- * is {@code null}, the String will be returned without an
- * an exception. An empty String is returned if len is negative.
- *
- *
- * StringUtils.right(null, *) = null
- * StringUtils.right(*, -ve) = ""
- * StringUtils.right("", *) = ""
- * StringUtils.right("abc", 0) = ""
- * StringUtils.right("abc", 2) = "bc"
- * StringUtils.right("abc", 4) = "abc"
- *
- *
- * @param str the String to get the rightmost characters from, may be null
- * @param len the length of the required String
- * @return the rightmost characters, {@code null} if null String input
- */
- public static String right(final String str, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0) {
- return EMPTY;
- }
- if (str.length() <= len) {
- return str;
- }
- return str.substring(str.length() - len);
- }
-
- /**
- * Gets {@code len} characters from the middle of a String.
- *
- * If {@code len} characters are not available, the remainder
- * of the String will be returned without an exception. If the
- * String is {@code null}, {@code null} will be returned.
- * An empty String is returned if len is negative or exceeds the
- * length of {@code str}.
- *
- *
- * StringUtils.mid(null, *, *) = null
- * StringUtils.mid(*, *, -ve) = ""
- * StringUtils.mid("", 0, *) = ""
- * StringUtils.mid("abc", 0, 2) = "ab"
- * StringUtils.mid("abc", 0, 4) = "abc"
- * StringUtils.mid("abc", 2, 4) = "c"
- * StringUtils.mid("abc", 4, 2) = ""
- * StringUtils.mid("abc", -2, 2) = "ab"
- *
- *
- * @param str the String to get the characters from, may be null
- * @param pos the position to start from, negative treated as zero
- * @param len the length of the required String
- * @return the middle characters, {@code null} if null String input
- */
- public static String mid(final String str, int pos, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0 || pos > str.length()) {
- return EMPTY;
- }
- if (pos < 0) {
- pos = 0;
- }
- if (str.length() <= pos + len) {
- return str.substring(pos);
- }
- return str.substring(pos, pos + len);
- }
-
- private static StringBuilder newStringBuilder(final int noOfItems) {
- return new StringBuilder(noOfItems * 16);
- }
-
- // SubStringAfter/SubStringBefore
- //-----------------------------------------------------------------------
- /**
- * Gets the substring before the first occurrence of a separator.
- * The separator is not returned.
- *
- * A {@code null} string input will return {@code null}.
- * An empty ("") string input will return the empty string.
- * A {@code null} separator will return the input string.
- *
- * If nothing is found, the string input is returned.
- *
- *
- * StringUtils.substringBefore(null, *) = null
- * StringUtils.substringBefore("", *) = ""
- * StringUtils.substringBefore("abc", "a") = ""
- * StringUtils.substringBefore("abcba", "b") = "a"
- * StringUtils.substringBefore("abc", "c") = "ab"
- * StringUtils.substringBefore("abc", "d") = "abc"
- * StringUtils.substringBefore("abc", "") = ""
- * StringUtils.substringBefore("abc", null) = "abc"
- *
- *
- * @param str the String to get a substring from, may be null
- * @param separator the String to search for, may be null
- * @return the substring before the first occurrence of the separator,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String substringBefore(final String str, final String separator) {
- if (isEmpty(str) || separator == null) {
- return str;
- }
- if (separator.isEmpty()) {
- return EMPTY;
- }
- final int pos = str.indexOf(separator);
- if (pos == INDEX_NOT_FOUND) {
- return str;
- }
- return str.substring(0, pos);
- }
-
- /**
- * Gets the substring after the first occurrence of a separator.
- * The separator is not returned.
- *
- * A {@code null} string input will return {@code null}.
- * An empty ("") string input will return the empty string.
- * A {@code null} separator will return the empty string if the
- * input string is not {@code null}.
- *
- * If nothing is found, the empty string is returned.
- *
- *
- * StringUtils.substringAfter(null, *) = null
- * StringUtils.substringAfter("", *) = ""
- * StringUtils.substringAfter(*, null) = ""
- * StringUtils.substringAfter("abc", "a") = "bc"
- * StringUtils.substringAfter("abcba", "b") = "cba"
- * StringUtils.substringAfter("abc", "c") = ""
- * StringUtils.substringAfter("abc", "d") = ""
- * StringUtils.substringAfter("abc", "") = "abc"
- *
- *
- * @param str the String to get a substring from, may be null
- * @param separator the String to search for, may be null
- * @return the substring after the first occurrence of the separator,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String substringAfter(final String str, final String separator) {
- if (isEmpty(str)) {
- return str;
- }
- if (separator == null) {
- return EMPTY;
- }
- final int pos = str.indexOf(separator);
- if (pos == INDEX_NOT_FOUND) {
- return EMPTY;
- }
- return str.substring(pos + separator.length());
- }
-
- /**
- * Gets the substring before the last occurrence of a separator.
- * The separator is not returned.
- *
- * A {@code null} string input will return {@code null}.
- * An empty ("") string input will return the empty string.
- * An empty or {@code null} separator will return the input string.
- *
- * If nothing is found, the string input is returned.
- *
- *
- * StringUtils.substringBeforeLast(null, *) = null
- * StringUtils.substringBeforeLast("", *) = ""
- * StringUtils.substringBeforeLast("abcba", "b") = "abc"
- * StringUtils.substringBeforeLast("abc", "c") = "ab"
- * StringUtils.substringBeforeLast("a", "a") = ""
- * StringUtils.substringBeforeLast("a", "z") = "a"
- * StringUtils.substringBeforeLast("a", null) = "a"
- * StringUtils.substringBeforeLast("a", "") = "a"
- *
- *
- * @param str the String to get a substring from, may be null
- * @param separator the String to search for, may be null
- * @return the substring before the last occurrence of the separator,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String substringBeforeLast(final String str, final String separator) {
- if (isEmpty(str) || isEmpty(separator)) {
- return str;
- }
- final int pos = str.lastIndexOf(separator);
- if (pos == INDEX_NOT_FOUND) {
- return str;
- }
- return str.substring(0, pos);
- }
-
- /**
- * Gets the substring after the last occurrence of a separator.
- * The separator is not returned.
- *
- * A {@code null} string input will return {@code null}.
- * An empty ("") string input will return the empty string.
- * An empty or {@code null} separator will return the empty string if
- * the input string is not {@code null}.
- *
- * If nothing is found, the empty string is returned.
- *
- *
- * StringUtils.substringAfterLast(null, *) = null
- * StringUtils.substringAfterLast("", *) = ""
- * StringUtils.substringAfterLast(*, "") = ""
- * StringUtils.substringAfterLast(*, null) = ""
- * StringUtils.substringAfterLast("abc", "a") = "bc"
- * StringUtils.substringAfterLast("abcba", "b") = "a"
- * StringUtils.substringAfterLast("abc", "c") = ""
- * StringUtils.substringAfterLast("a", "a") = ""
- * StringUtils.substringAfterLast("a", "z") = ""
- *
- *
- * @param str the String to get a substring from, may be null
- * @param separator the String to search for, may be null
- * @return the substring after the last occurrence of the separator,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String substringAfterLast(final String str, final String separator) {
- if (isEmpty(str)) {
- return str;
- }
- if (isEmpty(separator)) {
- return EMPTY;
- }
- final int pos = str.lastIndexOf(separator);
- if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
- return EMPTY;
- }
- return str.substring(pos + separator.length());
- }
-
- // Substring between
- //-----------------------------------------------------------------------
- /**
- * Gets the String that is nested in between two instances of the
- * same String.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} tag returns {@code null}.
- *
- *
- * StringUtils.substringBetween(null, *) = null
- * StringUtils.substringBetween("", "") = ""
- * StringUtils.substringBetween("", "tag") = null
- * StringUtils.substringBetween("tagabctag", null) = null
- * StringUtils.substringBetween("tagabctag", "") = ""
- * StringUtils.substringBetween("tagabctag", "tag") = "abc"
- *
- *
- * @param str the String containing the substring, may be null
- * @param tag the String before and after the substring, may be null
- * @return the substring, {@code null} if no match
- * @since 2.0
- */
- public static String substringBetween(final String str, final String tag) {
- return substringBetween(str, tag, tag);
- }
-
- /**
- * Gets the String that is nested in between two Strings.
- * Only the first match is returned.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} open/close returns {@code null} (no match).
- * An empty ("") open and close returns an empty string.
- *
- *
- * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
- * StringUtils.substringBetween(null, *, *) = null
- * StringUtils.substringBetween(*, null, *) = null
- * StringUtils.substringBetween(*, *, null) = null
- * StringUtils.substringBetween("", "", "") = ""
- * StringUtils.substringBetween("", "", "]") = null
- * StringUtils.substringBetween("", "[", "]") = null
- * StringUtils.substringBetween("yabcz", "", "") = ""
- * StringUtils.substringBetween("yabcz", "y", "z") = "abc"
- * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
- *
- *
- * @param str the String containing the substring, may be null
- * @param open the String before the substring, may be null
- * @param close the String after the substring, may be null
- * @return the substring, {@code null} if no match
- * @since 2.0
- */
- public static String substringBetween(final String str, final String open, final String close) {
- if (str == null || open == null || close == null) {
- return null;
- }
- final int start = str.indexOf(open);
- if (start != INDEX_NOT_FOUND) {
- final int end = str.indexOf(close, start + open.length());
- if (end != INDEX_NOT_FOUND) {
- return str.substring(start + open.length(), end);
- }
- }
- return null;
- }
-
- /**
- * Searches a String for substrings delimited by a start and end tag,
- * returning all matching substrings in an array.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} open/close returns {@code null} (no match).
- * An empty ("") open/close returns {@code null} (no match).
- *
- *
- * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
- * StringUtils.substringsBetween(null, *, *) = null
- * StringUtils.substringsBetween(*, null, *) = null
- * StringUtils.substringsBetween(*, *, null) = null
- * StringUtils.substringsBetween("", "[", "]") = []
- *
- *
- * @param str the String containing the substrings, null returns null, empty returns empty
- * @param open the String identifying the start of the substring, empty returns null
- * @param close the String identifying the end of the substring, empty returns null
- * @return a String Array of substrings, or {@code null} if no match
- * @since 2.3
- */
- public static String[] substringsBetween(final String str, final String open, final String close) {
- if (str == null || isEmpty(open) || isEmpty(close)) {
- return null;
- }
- final int strLen = str.length();
- if (strLen == 0) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- final int closeLen = close.length();
- final int openLen = open.length();
- final List list = new ArrayList<>();
- int pos = 0;
- while (pos < strLen - closeLen) {
- int start = str.indexOf(open, pos);
- if (start < 0) {
- break;
- }
- start += openLen;
- final int end = str.indexOf(close, start);
- if (end < 0) {
- break;
- }
- list.add(str.substring(start, end));
- pos = end + closeLen;
- }
- if (list.isEmpty()) {
- return null;
- }
- return list.toArray(new String [list.size()]);
- }
-
- // Nested extraction
- //-----------------------------------------------------------------------
-
- // Splitting
- //-----------------------------------------------------------------------
- /**
- * Splits the provided text into an array, using whitespace as the
- * separator.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.split(null) = null
- * StringUtils.split("") = []
- * StringUtils.split("abc def") = ["abc", "def"]
- * StringUtils.split("abc def") = ["abc", "def"]
- * StringUtils.split(" abc ") = ["abc"]
- *
- *
- * @param str the String to parse, may be null
- * @return an array of parsed Strings, {@code null} if null String input
- */
- public static String[] split(final String str) {
- return split(str, null, -1);
- }
-
- /**
- * Splits the provided text into an array, separator specified.
- * This is an alternative to using StringTokenizer.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.split(null, *) = null
- * StringUtils.split("", *) = []
- * StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
- * StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
- * StringUtils.split("a:b:c", '.') = ["a:b:c"]
- * StringUtils.split("a b c", ' ') = ["a", "b", "c"]
- *
- *
- * @param str the String to parse, may be null
- * @param separatorChar the character used as the delimiter
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.0
- */
- public static String[] split(final String str, final char separatorChar) {
- return splitWorker(str, separatorChar, false);
- }
-
- /**
- * Splits the provided text into an array, separators specified.
- * This is an alternative to using StringTokenizer.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separatorChars splits on whitespace.
- *
- *
- * StringUtils.split(null, *) = null
- * StringUtils.split("", *) = []
- * StringUtils.split("abc def", null) = ["abc", "def"]
- * StringUtils.split("abc def", " ") = ["abc", "def"]
- * StringUtils.split("abc def", " ") = ["abc", "def"]
- * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separatorChars the characters used as the delimiters,
- * {@code null} splits on whitespace
- * @return an array of parsed Strings, {@code null} if null String input
- */
- public static String[] split(final String str, final String separatorChars) {
- return splitWorker(str, separatorChars, -1, false);
- }
-
- /**
- * Splits the provided text into an array with a maximum length,
- * separators specified.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separatorChars splits on whitespace.
- *
- * If more than {@code max} delimited substrings are found, the last
- * returned string includes all characters after the first {@code max - 1}
- * returned strings (including separator characters).
- *
- *
- * StringUtils.split(null, *, *) = null
- * StringUtils.split("", *, *) = []
- * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separatorChars the characters used as the delimiters,
- * {@code null} splits on whitespace
- * @param max the maximum number of elements to include in the
- * array. A zero or negative value implies no limit
- * @return an array of parsed Strings, {@code null} if null String input
- */
- public static String[] split(final String str, final String separatorChars, final int max) {
- return splitWorker(str, separatorChars, max, false);
- }
-
- /**
- * Splits the provided text into an array, separator string specified.
- *
- * The separator(s) will not be included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separator splits on whitespace.
- *
- *
- * StringUtils.splitByWholeSeparator(null, *) = null
- * StringUtils.splitByWholeSeparator("", *) = []
- * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"]
- * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separator String containing the String to be used as a delimiter,
- * {@code null} splits on whitespace
- * @return an array of parsed Strings, {@code null} if null String was input
- */
- public static String[] splitByWholeSeparator(final String str, final String separator) {
- return splitByWholeSeparatorWorker(str, separator, -1, false ) ;
- }
-
- /**
- * Splits the provided text into an array, separator string specified.
- * Returns a maximum of {@code max} substrings.
- *
- * The separator(s) will not be included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separator splits on whitespace.
- *
- *
- * StringUtils.splitByWholeSeparator(null, *, *) = null
- * StringUtils.splitByWholeSeparator("", *, *) = []
- * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
- * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
- * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separator String containing the String to be used as a delimiter,
- * {@code null} splits on whitespace
- * @param max the maximum number of elements to include in the returned
- * array. A zero or negative value implies no limit.
- * @return an array of parsed Strings, {@code null} if null String was input
- */
- public static String[] splitByWholeSeparator( final String str, final String separator, final int max) {
- return splitByWholeSeparatorWorker(str, separator, max, false);
- }
-
- /**
- * Splits the provided text into an array, separator string specified.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separator splits on whitespace.
- *
- *
- * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = []
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separator String containing the String to be used as a delimiter,
- * {@code null} splits on whitespace
- * @return an array of parsed Strings, {@code null} if null String was input
- * @since 2.4
- */
- public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
- return splitByWholeSeparatorWorker(str, separator, -1, true);
- }
-
- /**
- * Splits the provided text into an array, separator string specified.
- * Returns a maximum of {@code max} substrings.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separator splits on whitespace.
- *
- *
- * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = []
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
- * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
- *
- *
- * @param str the String to parse, may be null
- * @param separator String containing the String to be used as a delimiter,
- * {@code null} splits on whitespace
- * @param max the maximum number of elements to include in the returned
- * array. A zero or negative value implies no limit.
- * @return an array of parsed Strings, {@code null} if null String was input
- * @since 2.4
- */
- public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
- return splitByWholeSeparatorWorker(str, separator, max, true);
- }
-
- /**
- * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
- *
- * @param str the String to parse, may be {@code null}
- * @param separator String containing the String to be used as a delimiter,
- * {@code null} splits on whitespace
- * @param max the maximum number of elements to include in the returned
- * array. A zero or negative value implies no limit.
- * @param preserveAllTokens if {@code true}, adjacent separators are
- * treated as empty token separators; if {@code false}, adjacent
- * separators are treated as one separator.
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.4
- */
- private static String[] splitByWholeSeparatorWorker(
- final String str, final String separator, final int max, final boolean preserveAllTokens) {
- if (str == null) {
- return null;
- }
-
- final int len = str.length();
-
- if (len == 0) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
-
- if (separator == null || EMPTY.equals(separator)) {
- // Split on whitespace.
- return splitWorker(str, null, max, preserveAllTokens);
- }
-
- final int separatorLength = separator.length();
-
- final ArrayList substrings = new ArrayList<>();
- int numberOfSubstrings = 0;
- int beg = 0;
- int end = 0;
- while (end < len) {
- end = str.indexOf(separator, beg);
-
- if (end > -1) {
- if (end > beg) {
- numberOfSubstrings += 1;
-
- if (numberOfSubstrings == max) {
- end = len;
- substrings.add(str.substring(beg));
- } else {
- // The following is OK, because String.substring( beg, end ) excludes
- // the character at the position 'end'.
- substrings.add(str.substring(beg, end));
-
- // Set the starting point for the next search.
- // The following is equivalent to beg = end + (separatorLength - 1) + 1,
- // which is the right calculation:
- beg = end + separatorLength;
- }
- } else {
- // We found a consecutive occurrence of the separator, so skip it.
- if (preserveAllTokens) {
- numberOfSubstrings += 1;
- if (numberOfSubstrings == max) {
- end = len;
- substrings.add(str.substring(beg));
- } else {
- substrings.add(EMPTY);
- }
- }
- beg = end + separatorLength;
- }
- } else {
- // String.substring( beg ) goes from 'beg' to the end of the String.
- substrings.add(str.substring(beg));
- end = len;
- }
- }
-
- return substrings.toArray(new String[substrings.size()]);
- }
-
- // -----------------------------------------------------------------------
- /**
- * Splits the provided text into an array, using whitespace as the
- * separator, preserving all tokens, including empty tokens created by
- * adjacent separators. This is an alternative to using StringTokenizer.
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.splitPreserveAllTokens(null) = null
- * StringUtils.splitPreserveAllTokens("") = []
- * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]
- * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]
- * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]
- *
- *
- * @param str the String to parse, may be {@code null}
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.1
- */
- public static String[] splitPreserveAllTokens(final String str) {
- return splitWorker(str, null, -1, true);
- }
-
- /**
- * Splits the provided text into an array, separator specified,
- * preserving all tokens, including empty tokens created by adjacent
- * separators. This is an alternative to using StringTokenizer.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.splitPreserveAllTokens(null, *) = null
- * StringUtils.splitPreserveAllTokens("", *) = []
- * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"]
- * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"]
- * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"]
- * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
- * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"]
- * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""]
- * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""]
- * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"]
- * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"]
- * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""]
- *
- *
- * @param str the String to parse, may be {@code null}
- * @param separatorChar the character used as the delimiter,
- * {@code null} splits on whitespace
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.1
- */
- public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
- return splitWorker(str, separatorChar, true);
- }
-
- /**
- * Performs the logic for the {@code split} and
- * {@code splitPreserveAllTokens} methods that do not return a
- * maximum array length.
- *
- * @param str the String to parse, may be {@code null}
- * @param separatorChar the separate character
- * @param preserveAllTokens if {@code true}, adjacent separators are
- * treated as empty token separators; if {@code false}, adjacent
- * separators are treated as one separator.
- * @return an array of parsed Strings, {@code null} if null String input
- */
- private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
- // Performance tuned for 2.0 (JDK1.4)
-
- if (str == null) {
- return null;
- }
- final int len = str.length();
- if (len == 0) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- final List list = new ArrayList<>();
- int i = 0, start = 0;
- boolean match = false;
- boolean lastMatch = false;
- while (i < len) {
- if (str.charAt(i) == separatorChar) {
- if (match || preserveAllTokens) {
- list.add(str.substring(start, i));
- match = false;
- lastMatch = true;
- }
- start = ++i;
- continue;
- }
- lastMatch = false;
- match = true;
- i++;
- }
- if (match || preserveAllTokens && lastMatch) {
- list.add(str.substring(start, i));
- }
- return list.toArray(new String[list.size()]);
- }
-
- /**
- * Splits the provided text into an array, separators specified,
- * preserving all tokens, including empty tokens created by adjacent
- * separators. This is an alternative to using StringTokenizer.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * For more control over the split use the StrTokenizer class.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separatorChars splits on whitespace.
- *
- *
- * StringUtils.splitPreserveAllTokens(null, *) = null
- * StringUtils.splitPreserveAllTokens("", *) = []
- * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"]
- * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"]
- * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"]
- * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
- * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""]
- * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
- * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"]
- * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"]
- * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"]
- * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""]
- *
- *
- * @param str the String to parse, may be {@code null}
- * @param separatorChars the characters used as the delimiters,
- * {@code null} splits on whitespace
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.1
- */
- public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
- return splitWorker(str, separatorChars, -1, true);
- }
-
- /**
- * Splits the provided text into an array with a maximum length,
- * separators specified, preserving all tokens, including empty tokens
- * created by adjacent separators.
- *
- * The separator is not included in the returned String array.
- * Adjacent separators are treated as separators for empty tokens.
- * Adjacent separators are treated as one separator.
- *
- * A {@code null} input String returns {@code null}.
- * A {@code null} separatorChars splits on whitespace.
- *
- * If more than {@code max} delimited substrings are found, the last
- * returned string includes all characters after the first {@code max - 1}
- * returned strings (including separator characters).
- *
- *
- * StringUtils.splitPreserveAllTokens(null, *, *) = null
- * StringUtils.splitPreserveAllTokens("", *, *) = []
- * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
- * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
- * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"]
- * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"]
- * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"]
- *
- *
- * @param str the String to parse, may be {@code null}
- * @param separatorChars the characters used as the delimiters,
- * {@code null} splits on whitespace
- * @param max the maximum number of elements to include in the
- * array. A zero or negative value implies no limit
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.1
- */
- public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
- return splitWorker(str, separatorChars, max, true);
- }
-
- /**
- * Performs the logic for the {@code split} and
- * {@code splitPreserveAllTokens} methods that return a maximum array
- * length.
- *
- * @param str the String to parse, may be {@code null}
- * @param separatorChars the separate character
- * @param max the maximum number of elements to include in the
- * array. A zero or negative value implies no limit.
- * @param preserveAllTokens if {@code true}, adjacent separators are
- * treated as empty token separators; if {@code false}, adjacent
- * separators are treated as one separator.
- * @return an array of parsed Strings, {@code null} if null String input
- */
- private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
- // Performance tuned for 2.0 (JDK1.4)
- // Direct code is quicker than StringTokenizer.
- // Also, StringTokenizer uses isSpace() not isWhitespace()
-
- if (str == null) {
- return null;
- }
- final int len = str.length();
- if (len == 0) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- final List list = new ArrayList<>();
- int sizePlus1 = 1;
- int i = 0, start = 0;
- boolean match = false;
- boolean lastMatch = false;
- if (separatorChars == null) {
- // Null separator means use whitespace
- while (i < len) {
- if (Character.isWhitespace(str.charAt(i))) {
- if (match || preserveAllTokens) {
- lastMatch = true;
- if (sizePlus1++ == max) {
- i = len;
- lastMatch = false;
- }
- list.add(str.substring(start, i));
- match = false;
- }
- start = ++i;
- continue;
- }
- lastMatch = false;
- match = true;
- i++;
- }
- } else if (separatorChars.length() == 1) {
- // Optimise 1 character case
- final char sep = separatorChars.charAt(0);
- while (i < len) {
- if (str.charAt(i) == sep) {
- if (match || preserveAllTokens) {
- lastMatch = true;
- if (sizePlus1++ == max) {
- i = len;
- lastMatch = false;
- }
- list.add(str.substring(start, i));
- match = false;
- }
- start = ++i;
- continue;
- }
- lastMatch = false;
- match = true;
- i++;
- }
- } else {
- // standard case
- while (i < len) {
- if (separatorChars.indexOf(str.charAt(i)) >= 0) {
- if (match || preserveAllTokens) {
- lastMatch = true;
- if (sizePlus1++ == max) {
- i = len;
- lastMatch = false;
- }
- list.add(str.substring(start, i));
- match = false;
- }
- start = ++i;
- continue;
- }
- lastMatch = false;
- match = true;
- i++;
- }
- }
- if (match || preserveAllTokens && lastMatch) {
- list.add(str.substring(start, i));
- }
- return list.toArray(new String[list.size()]);
- }
-
- /**
- * Splits a String by Character type as returned by
- * {@code java.lang.Character.getType(char)}. Groups of contiguous
- * characters of the same type are returned as complete tokens.
- *
- * StringUtils.splitByCharacterType(null) = null
- * StringUtils.splitByCharacterType("") = []
- * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
- * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
- * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
- * StringUtils.splitByCharacterType("number5") = ["number", "5"]
- * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"]
- * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"]
- * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"]
- *
- * @param str the String to split, may be {@code null}
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.4
- */
- public static String[] splitByCharacterType(final String str) {
- return splitByCharacterType(str, false);
- }
-
- /**
- * Splits a String by Character type as returned by
- * {@code java.lang.Character.getType(char)}. Groups of contiguous
- * characters of the same type are returned as complete tokens, with the
- * following exception: the character of type
- * {@code Character.UPPERCASE_LETTER}, if any, immediately
- * preceding a token of type {@code Character.LOWERCASE_LETTER}
- * will belong to the following token rather than to the preceding, if any,
- * {@code Character.UPPERCASE_LETTER} token.
- *
- * StringUtils.splitByCharacterTypeCamelCase(null) = null
- * StringUtils.splitByCharacterTypeCamelCase("") = []
- * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
- * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
- * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
- * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"]
- * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"]
- * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"]
- * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"]
- *
- * @param str the String to split, may be {@code null}
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.4
- */
- public static String[] splitByCharacterTypeCamelCase(final String str) {
- return splitByCharacterType(str, true);
- }
-
- /**
- * Splits a String by Character type as returned by
- * {@code java.lang.Character.getType(char)}. Groups of contiguous
- * characters of the same type are returned as complete tokens, with the
- * following exception: if {@code camelCase} is {@code true},
- * the character of type {@code Character.UPPERCASE_LETTER}, if any,
- * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
- * will belong to the following token rather than to the preceding, if any,
- * {@code Character.UPPERCASE_LETTER} token.
- * @param str the String to split, may be {@code null}
- * @param camelCase whether to use so-called "camel-case" for letter types
- * @return an array of parsed Strings, {@code null} if null String input
- * @since 2.4
- */
- private static String[] splitByCharacterType(final String str, final boolean camelCase) {
- if (str == null) {
- return null;
- }
- if (str.isEmpty()) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- final char[] c = str.toCharArray();
- final List list = new ArrayList<>();
- int tokenStart = 0;
- int currentType = Character.getType(c[tokenStart]);
- for (int pos = tokenStart + 1; pos < c.length; pos++) {
- final int type = Character.getType(c[pos]);
- if (type == currentType) {
- continue;
- }
- if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
- final int newTokenStart = pos - 1;
- if (newTokenStart != tokenStart) {
- list.add(new String(c, tokenStart, newTokenStart - tokenStart));
- tokenStart = newTokenStart;
- }
- } else {
- list.add(new String(c, tokenStart, pos - tokenStart));
- tokenStart = pos;
- }
- currentType = type;
- }
- list.add(new String(c, tokenStart, c.length - tokenStart));
- return list.toArray(new String[list.size()]);
- }
-
- // Joining
- //-----------------------------------------------------------------------
- /**
- * Joins the elements of the provided array into a single String
- * containing the provided list of elements.
- *
- * No separator is added to the joined String.
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null) = null
- * StringUtils.join([]) = ""
- * StringUtils.join([null]) = ""
- * StringUtils.join(["a", "b", "c"]) = "abc"
- * StringUtils.join([null, "", "a"]) = "a"
- *
- *
- * @param the specific type of values to join together
- * @param elements the values to join together, may be null
- * @return the joined String, {@code null} if null array input
- * @since 2.0
- * @since 3.0 Changed signature to use varargs
- */
- @SafeVarargs
- public static String join(final T... elements) {
- return join(elements, null);
- }
-
- /**
- * Joins the elements of the provided array into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
- * StringUtils.join(["a", "b", "c"], null) = "abc"
- * StringUtils.join([null, "", "a"], ';') = ";;a"
- *
- *
- * @param array the array of values to join together, may be null
- * @param separator the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 2.0
- */
- public static String join(final Object[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final long[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final int[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final short[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final byte[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final char[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final float[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final double[] array, final char separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
-
- /**
- * Joins the elements of the provided array into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
- * StringUtils.join(["a", "b", "c"], null) = "abc"
- * StringUtils.join([null, "", "a"], ';') = ";;a"
- *
- *
- * @param array the array of values to join together, may be null
- * @param separator the separator character to use
- * @param startIndex the first index to start joining from. It is
- * an error to pass in an end index past the end of the array
- * @param endIndex the index to stop joining from (exclusive). It is
- * an error to pass in an end index past the end of the array
- * @return the joined String, {@code null} if null array input
- * @since 2.0
- */
- public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- if (array[i] != null) {
- buf.append(array[i]);
- }
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
- /**
- *
- * Joins the elements of the provided array into a single String containing the provided list of elements.
- *
- *
- *
- * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
- * by empty strings.
- *
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join([1, 2, 3], ';') = "1;2;3"
- * StringUtils.join([1, 2, 3], null) = "123"
- *
- *
- * @param array
- * the array of values to join together, may be null
- * @param separator
- * the separator character to use
- * @param startIndex
- * the first index to start joining from. It is an error to pass in an end index past the end of the
- * array
- * @param endIndex
- * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
- * the array
- * @return the joined String, {@code null} if null array input
- * @since 3.2
- */
- public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final StringBuilder buf = newStringBuilder(noOfItems);
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- buf.append(array[i]);
- }
- return buf.toString();
- }
-
-
- /**
- * Joins the elements of the provided array into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * A {@code null} separator is the same as an empty String ("").
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
- * StringUtils.join(["a", "b", "c"], null) = "abc"
- * StringUtils.join(["a", "b", "c"], "") = "abc"
- * StringUtils.join([null, "", "a"], ',') = ",,a"
- *
- *
- * @param array the array of values to join together, may be null
- * @param separator the separator character to use, null treated as ""
- * @return the joined String, {@code null} if null array input
- */
- public static String join(final Object[] array, final String separator) {
- if (array == null) {
- return null;
- }
- return join(array, separator, 0, array.length);
- }
-
- /**
- * Joins the elements of the provided array into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * A {@code null} separator is the same as an empty String ("").
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *, *, *) = null
- * StringUtils.join([], *, *, *) = ""
- * StringUtils.join([null], *, *, *) = ""
- * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c"
- * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c"
- * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c"
- * StringUtils.join(["a", "b", "c"], "--", 2, 2) = ""
- * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc"
- * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc"
- * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a"
- *
- *
- * @param array the array of values to join together, may be null
- * @param separator the separator character to use, null treated as ""
- * @param startIndex the first index to start joining from.
- * @param endIndex the index to stop joining from (exclusive).
- * @return the joined String, {@code null} if null array input; or the empty string
- * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
- * {@code endIndex - startIndex}
- * @throws ArrayIndexOutOfBoundsException ife
- * {@code startIndex < 0} or
- * {@code startIndex >= array.length()} or
- * {@code endIndex < 0} or
- * {@code endIndex > array.length()}
- */
- public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
- if (array == null) {
- return null;
- }
- if (separator == null) {
- separator = EMPTY;
- }
-
- // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator))
- // (Assuming that all Strings are roughly equally long)
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
-
- final StringBuilder buf = newStringBuilder(noOfItems);
-
- for (int i = startIndex; i < endIndex; i++) {
- if (i > startIndex) {
- buf.append(separator);
- }
- if (array[i] != null) {
- buf.append(array[i]);
- }
- }
- return buf.toString();
- }
-
- /**
- * Joins the elements of the provided {@code Iterator} into
- * a single String containing the provided elements.
- *
- * No delimiter is added before or after the list. Null objects or empty
- * strings within the iteration are represented by empty strings.
- *
- * See the examples here: {@link #join(Object[],char)}.
- *
- * @param iterator the {@code Iterator} of values to join together, may be null
- * @param separator the separator character to use
- * @return the joined String, {@code null} if null iterator input
- * @since 2.0
- */
- public static String join(final Iterator> iterator, final char separator) {
-
- // handle null, zero and one elements before building a buffer
- if (iterator == null) {
- return null;
- }
- if (!iterator.hasNext()) {
- return EMPTY;
- }
- final Object first = iterator.next();
- if (!iterator.hasNext()) {
- return Objects.toString(first, EMPTY);
- }
-
- // two or more elements
- final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
- if (first != null) {
- buf.append(first);
- }
-
- while (iterator.hasNext()) {
- buf.append(separator);
- final Object obj = iterator.next();
- if (obj != null) {
- buf.append(obj);
- }
- }
-
- return buf.toString();
- }
-
- /**
- * Joins the elements of the provided {@code Iterator} into
- * a single String containing the provided elements.
- *
- * No delimiter is added before or after the list.
- * A {@code null} separator is the same as an empty String ("").
- *
- * See the examples here: {@link #join(Object[],String)}.
- *
- * @param iterator the {@code Iterator} of values to join together, may be null
- * @param separator the separator character to use, null treated as ""
- * @return the joined String, {@code null} if null iterator input
- */
- public static String join(final Iterator> iterator, final String separator) {
-
- // handle null, zero and one elements before building a buffer
- if (iterator == null) {
- return null;
- }
- if (!iterator.hasNext()) {
- return EMPTY;
- }
- final Object first = iterator.next();
- if (!iterator.hasNext()) {
- return Objects.toString(first, "");
- }
-
- // two or more elements
- final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
- if (first != null) {
- buf.append(first);
- }
-
- while (iterator.hasNext()) {
- if (separator != null) {
- buf.append(separator);
- }
- final Object obj = iterator.next();
- if (obj != null) {
- buf.append(obj);
- }
- }
- return buf.toString();
- }
-
- /**
- * Joins the elements of the provided {@code Iterable} into
- * a single String containing the provided elements.
- *
- * No delimiter is added before or after the list. Null objects or empty
- * strings within the iteration are represented by empty strings.
- *
- * See the examples here: {@link #join(Object[],char)}.
- *
- * @param iterable the {@code Iterable} providing the values to join together, may be null
- * @param separator the separator character to use
- * @return the joined String, {@code null} if null iterator input
- * @since 2.3
- */
- public static String join(final Iterable> iterable, final char separator) {
- if (iterable == null) {
- return null;
- }
- return join(iterable.iterator(), separator);
- }
-
- /**
- * Joins the elements of the provided {@code Iterable} into
- * a single String containing the provided elements.
- *
- * No delimiter is added before or after the list.
- * A {@code null} separator is the same as an empty String ("").
- *
- * See the examples here: {@link #join(Object[],String)}.
- *
- * @param iterable the {@code Iterable} providing the values to join together, may be null
- * @param separator the separator character to use, null treated as ""
- * @return the joined String, {@code null} if null iterator input
- * @since 2.3
- */
- public static String join(final Iterable> iterable, final String separator) {
- if (iterable == null) {
- return null;
- }
- return join(iterable.iterator(), separator);
- }
-
- /**
- * Joins the elements of the provided {@code List} into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
- * StringUtils.join(["a", "b", "c"], null) = "abc"
- * StringUtils.join([null, "", "a"], ';') = ";;a"
- *
- *
- * @param list the {@code List} of values to join together, may be null
- * @param separator the separator character to use
- * @param startIndex the first index to start joining from. It is
- * an error to pass in an end index past the end of the list
- * @param endIndex the index to stop joining from (exclusive). It is
- * an error to pass in an end index past the end of the list
- * @return the joined String, {@code null} if null list input
- * @since 3.8
- */
- public static String join(final List> list, final char separator, final int startIndex, final int endIndex) {
- if (list == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final List> subList = list.subList(startIndex, endIndex);
- return join(subList.iterator(), separator);
- }
-
- /**
- * Joins the elements of the provided {@code List} into a single String
- * containing the provided list of elements.
- *
- * No delimiter is added before or after the list.
- * Null objects or empty strings within the array are represented by
- * empty strings.
- *
- *
- * StringUtils.join(null, *) = null
- * StringUtils.join([], *) = ""
- * StringUtils.join([null], *) = ""
- * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
- * StringUtils.join(["a", "b", "c"], null) = "abc"
- * StringUtils.join([null, "", "a"], ';') = ";;a"
- *
- *
- * @param list the {@code List} of values to join together, may be null
- * @param separator the separator character to use
- * @param startIndex the first index to start joining from. It is
- * an error to pass in an end index past the end of the list
- * @param endIndex the index to stop joining from (exclusive). It is
- * an error to pass in an end index past the end of the list
- * @return the joined String, {@code null} if null list input
- * @since 3.8
- */
- public static String join(final List> list, final String separator, final int startIndex, final int endIndex) {
- if (list == null) {
- return null;
- }
- final int noOfItems = endIndex - startIndex;
- if (noOfItems <= 0) {
- return EMPTY;
- }
- final List> subList = list.subList(startIndex, endIndex);
- return join(subList.iterator(), separator);
- }
-
- /**
- * Joins the elements of the provided varargs into a
- * single String containing the provided elements.
- *
- * No delimiter is added before or after the list.
- * {@code null} elements and separator are treated as empty Strings ("").
- *
- *
- * StringUtils.joinWith(",", {"a", "b"}) = "a,b"
- * StringUtils.joinWith(",", {"a", "b",""}) = "a,b,"
- * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b"
- * StringUtils.joinWith(null, {"a", "b"}) = "ab"
- *
- *
- * @param separator the separator character to use, null treated as ""
- * @param objects the varargs providing the values to join together. {@code null} elements are treated as ""
- * @return the joined String.
- * @throws IllegalArgumentException if a null varargs is provided
- * @since 3.5
- */
- public static String joinWith(final String separator, final Object... objects) {
- if (objects == null) {
- throw new IllegalArgumentException("Object varargs must not be null");
- }
-
- final String sanitizedSeparator = defaultString(separator);
-
- final StringBuilder result = new StringBuilder();
-
- final Iterator iterator = Arrays.asList(objects).iterator();
- while (iterator.hasNext()) {
- final String value = Objects.toString(iterator.next(), "");
- result.append(value);
-
- if (iterator.hasNext()) {
- result.append(sanitizedSeparator);
- }
- }
-
- return result.toString();
- }
-
- // Delete
- //-----------------------------------------------------------------------
- /**
- * Deletes all whitespaces from a String as defined by
- * {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.deleteWhitespace(null) = null
- * StringUtils.deleteWhitespace("") = ""
- * StringUtils.deleteWhitespace("abc") = "abc"
- * StringUtils.deleteWhitespace(" ab c ") = "abc"
- *
- *
- * @param str the String to delete whitespace from, may be null
- * @return the String without whitespaces, {@code null} if null String input
- */
- public static String deleteWhitespace(final String str) {
- if (isEmpty(str)) {
- return str;
- }
- final int sz = str.length();
- final char[] chs = new char[sz];
- int count = 0;
- for (int i = 0; i < sz; i++) {
- if (!Character.isWhitespace(str.charAt(i))) {
- chs[count++] = str.charAt(i);
- }
- }
- if (count == sz) {
- return str;
- }
- return new String(chs, 0, count);
- }
-
- // Remove
- //-----------------------------------------------------------------------
- /**
- * Removes a substring only if it is at the beginning of a source string,
- * otherwise returns the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- * A {@code null} search string will return the source string.
- *
- *
- * StringUtils.removeStart(null, *) = null
- * StringUtils.removeStart("", *) = ""
- * StringUtils.removeStart(*, null) = *
- * StringUtils.removeStart("www.domain.com", "www.") = "domain.com"
- * StringUtils.removeStart("domain.com", "www.") = "domain.com"
- * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
- * StringUtils.removeStart("abc", "") = "abc"
- *
- *
- * @param str the source String to search, may be null
- * @param remove the String to search for and remove, may be null
- * @return the substring with the string removed if found,
- * {@code null} if null String input
- * @since 2.1
- */
- public static String removeStart(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (str.startsWith(remove)){
- return str.substring(remove.length());
- }
- return str;
- }
-
- /**
- * Case insensitive removal of a substring if it is at the beginning of a source string,
- * otherwise returns the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- * A {@code null} search string will return the source string.
- *
- *
- * StringUtils.removeStartIgnoreCase(null, *) = null
- * StringUtils.removeStartIgnoreCase("", *) = ""
- * StringUtils.removeStartIgnoreCase(*, null) = *
- * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com"
- * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com"
- * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com"
- * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
- * StringUtils.removeStartIgnoreCase("abc", "") = "abc"
- *
- *
- * @param str the source String to search, may be null
- * @param remove the String to search for (case insensitive) and remove, may be null
- * @return the substring with the string removed if found,
- * {@code null} if null String input
- * @since 2.4
- */
- public static String removeStartIgnoreCase(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (startsWithIgnoreCase(str, remove)) {
- return str.substring(remove.length());
- }
- return str;
- }
-
- /**
- * Removes a substring only if it is at the end of a source string,
- * otherwise returns the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- * A {@code null} search string will return the source string.
- *
- *
- * StringUtils.removeEnd(null, *) = null
- * StringUtils.removeEnd("", *) = ""
- * StringUtils.removeEnd(*, null) = *
- * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com"
- * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain"
- * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
- * StringUtils.removeEnd("abc", "") = "abc"
- *
- *
- * @param str the source String to search, may be null
- * @param remove the String to search for and remove, may be null
- * @return the substring with the string removed if found,
- * {@code null} if null String input
- * @since 2.1
- */
- public static String removeEnd(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (str.endsWith(remove)) {
- return str.substring(0, str.length() - remove.length());
- }
- return str;
- }
-
- /**
- * Case insensitive removal of a substring if it is at the end of a source string,
- * otherwise returns the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- * A {@code null} search string will return the source string.
- *
- *
- * StringUtils.removeEndIgnoreCase(null, *) = null
- * StringUtils.removeEndIgnoreCase("", *) = ""
- * StringUtils.removeEndIgnoreCase(*, null) = *
- * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com"
- * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain"
- * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
- * StringUtils.removeEndIgnoreCase("abc", "") = "abc"
- * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
- * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
- *
- *
- * @param str the source String to search, may be null
- * @param remove the String to search for (case insensitive) and remove, may be null
- * @return the substring with the string removed if found,
- * {@code null} if null String input
- * @since 2.4
- */
- public static String removeEndIgnoreCase(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (endsWithIgnoreCase(str, remove)) {
- return str.substring(0, str.length() - remove.length());
- }
- return str;
- }
-
- /**
- * Removes all occurrences of a substring from within the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- * A {@code null} remove string will return the source string.
- * An empty ("") remove string will return the source string.
- *
- *
- * StringUtils.remove(null, *) = null
- * StringUtils.remove("", *) = ""
- * StringUtils.remove(*, null) = *
- * StringUtils.remove(*, "") = *
- * StringUtils.remove("queued", "ue") = "qd"
- * StringUtils.remove("queued", "zz") = "queued"
- *
- *
- * @param str the source String to search, may be null
- * @param remove the String to search for and remove, may be null
- * @return the substring with the string removed if found,
- * {@code null} if null String input
- * @since 2.1
- */
- public static String remove(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- return replace(str, remove, EMPTY, -1);
- }
-
- /**
- *
- * Case insensitive removal of all occurrences of a substring from within
- * the source string.
- *
- *
- *
- * A {@code null} source string will return {@code null}. An empty ("")
- * source string will return the empty string. A {@code null} remove string
- * will return the source string. An empty ("") remove string will return
- * the source string.
- *
- *
- *
- * StringUtils.removeIgnoreCase(null, *) = null
- * StringUtils.removeIgnoreCase("", *) = ""
- * StringUtils.removeIgnoreCase(*, null) = *
- * StringUtils.removeIgnoreCase(*, "") = *
- * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
- * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
- * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
- * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
- *
- *
- * @param str
- * the source String to search, may be null
- * @param remove
- * the String to search for (case insensitive) and remove, may be
- * null
- * @return the substring with the string removed if found, {@code null} if
- * null String input
- * @since 3.5
- */
- public static String removeIgnoreCase(final String str, final String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- return replaceIgnoreCase(str, remove, EMPTY, -1);
- }
-
- /**
- * Removes all occurrences of a character from within the source string.
- *
- * A {@code null} source string will return {@code null}.
- * An empty ("") source string will return the empty string.
- *
- *
- * StringUtils.remove(null, *) = null
- * StringUtils.remove("", *) = ""
- * StringUtils.remove("queued", 'u') = "qeed"
- * StringUtils.remove("queued", 'z') = "queued"
- *
- *
- * @param str the source String to search, may be null
- * @param remove the char to search for and remove, may be null
- * @return the substring with the char removed if found,
- * {@code null} if null String input
- * @since 2.1
- */
- public static String remove(final String str, final char remove) {
- if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
- return str;
- }
- final char[] chars = str.toCharArray();
- int pos = 0;
- for (int i = 0; i < chars.length; i++) {
- if (chars[i] != remove) {
- chars[pos++] = chars[i];
- }
- }
- return new String(chars, 0, pos);
- }
-
- /**
- * Removes each substring of the text String that matches the given regular expression.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll(regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
- * is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.removeAll(null, *) = null
- * StringUtils.removeAll("any", (String) null) = "any"
- * StringUtils.removeAll("any", "") = "any"
- * StringUtils.removeAll("any", ".*") = ""
- * StringUtils.removeAll("any", ".+") = ""
- * StringUtils.removeAll("abc", ".?") = ""
- * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB"
- * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB"
- * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression to which this string is to be matched
- * @return the text with any removes processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replaceAll(String, String, String)
- * @see #removePattern(String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- * @since 3.5
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String removeAll(final String text, final String regex) {
- return RegExUtils.removeAll(text, regex);
- }
-
- /**
- * Removes the first substring of the text string that matches the given regular expression.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceFirst(regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * The {@link Pattern#DOTALL} option is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.removeFirst(null, *) = null
- * StringUtils.removeFirst("any", (String) null) = "any"
- * StringUtils.removeFirst("any", "") = "any"
- * StringUtils.removeFirst("any", ".*") = ""
- * StringUtils.removeFirst("any", ".+") = ""
- * StringUtils.removeFirst("abc", ".?") = "bc"
- * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B"
- * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB"
- * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123"
- * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc"
- *
- *
- * @param text text to remove from, may be null
- * @param regex the regular expression to which this string is to be matched
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replaceFirst(String, String, String)
- * @see String#replaceFirst(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- * @since 3.5
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String removeFirst(final String text, final String regex) {
- return replaceFirst(text, regex, EMPTY);
- }
-
- // Replacing
- //-----------------------------------------------------------------------
- /**
- * Replaces a String with another String inside a larger String, once.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceOnce(null, *, *) = null
- * StringUtils.replaceOnce("", *, *) = ""
- * StringUtils.replaceOnce("any", null, *) = "any"
- * StringUtils.replaceOnce("any", *, null) = "any"
- * StringUtils.replaceOnce("any", "", *) = "any"
- * StringUtils.replaceOnce("aba", "a", null) = "aba"
- * StringUtils.replaceOnce("aba", "a", "") = "ba"
- * StringUtils.replaceOnce("aba", "a", "z") = "zba"
- *
- *
- * @see #replace(String text, String searchString, String replacement, int max)
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for, may be null
- * @param replacement the String to replace with, may be null
- * @return the text with any replacements processed,
- * {@code null} if null String input
- */
- public static String replaceOnce(final String text, final String searchString, final String replacement) {
- return replace(text, searchString, replacement, 1);
- }
-
- /**
- * Case insensitively replaces a String with another String inside a larger String, once.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceOnceIgnoreCase(null, *, *) = null
- * StringUtils.replaceOnceIgnoreCase("", *, *) = ""
- * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any"
- * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any"
- * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any"
- * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba"
- * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba"
- * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba"
- * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
- *
- *
- * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for (case insensitive), may be null
- * @param replacement the String to replace with, may be null
- * @return the text with any replacements processed,
- * {@code null} if null String input
- * @since 3.5
- */
- public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
- return replaceIgnoreCase(text, searchString, replacement, 1);
- }
-
- /**
- * Replaces each substring of the source String that matches the given regular expression with the given
- * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
- *
- * This call is a {@code null} safe equivalent to:
- *
- * {@code source.replaceAll("(?s)" + regex, replacement)}
- * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replacePattern(null, *, *) = null
- * StringUtils.replacePattern("any", (String) null, *) = "any"
- * StringUtils.replacePattern("any", *, null) = "any"
- * StringUtils.replacePattern("", "", "zzz") = "zzz"
- * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
- * StringUtils.replacePattern("", ".+", "zzz") = ""
- * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
- * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
- * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
- * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
- * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
- *
- *
- * @param source
- * the source string
- * @param regex
- * the regular expression to which this string is to be matched
- * @param replacement
- * the string to be substituted for each match
- * @return The resulting {@code String}
- * @see #replaceAll(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern#DOTALL
- * @since 3.2
- * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String replacePattern(final String source, final String regex, final String replacement) {
- return RegExUtils.replacePattern(source, regex, replacement);
- }
-
- /**
- * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
- *
- *
- * This call is a {@code null} safe equivalent to:
- *
- * {@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}
- * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.removePattern(null, *) = null
- * StringUtils.removePattern("any", (String) null) = "any"
- * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB"
- * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123"
- *
- *
- * @param source
- * the source string
- * @param regex
- * the regular expression to which this string is to be matched
- * @return The resulting {@code String}
- * @see #replacePattern(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern#DOTALL
- * @since 3.2
- * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String removePattern(final String source, final String regex) {
- return RegExUtils.removePattern(source, regex);
- }
-
- /**
- * Replaces each substring of the text String that matches the given regular expression
- * with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceAll(regex, replacement)}
- * {@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
- * is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.replaceAll(null, *, *) = null
- * StringUtils.replaceAll("any", (String) null, *) = "any"
- * StringUtils.replaceAll("any", *, null) = "any"
- * StringUtils.replaceAll("", "", "zzz") = "zzz"
- * StringUtils.replaceAll("", ".*", "zzz") = "zzz"
- * StringUtils.replaceAll("", ".+", "zzz") = ""
- * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ"
- * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz"
- * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z"
- * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123"
- * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
- * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
- * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression to which this string is to be matched
- * @param replacement the string to be substituted for each match
- * @return the text with any replacements processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see #replacePattern(String, String, String)
- * @see String#replaceAll(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- * @since 3.5
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String replaceAll(final String text, final String regex, final String replacement) {
- return RegExUtils.replaceAll(text, regex, replacement);
- }
-
- /**
- * Replaces the first substring of the text string that matches the given regular expression
- * with the given replacement.
- *
- * This method is a {@code null} safe equivalent to:
- *
- * {@code text.replaceFirst(regex, replacement)}
- * {@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}
- *
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- * The {@link Pattern#DOTALL} option is NOT automatically added.
- * To use the DOTALL option prepend "(?s)" to the regex.
- * DOTALL is also known as single-line mode in Perl.
- *
- *
- * StringUtils.replaceFirst(null, *, *) = null
- * StringUtils.replaceFirst("any", (String) null, *) = "any"
- * StringUtils.replaceFirst("any", *, null) = "any"
- * StringUtils.replaceFirst("", "", "zzz") = "zzz"
- * StringUtils.replaceFirst("", ".*", "zzz") = "zzz"
- * StringUtils.replaceFirst("", ".+", "zzz") = ""
- * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc"
- * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>"
- * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z"
- * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123"
- * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc"
- * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc"
- * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit"
- *
- *
- * @param text text to search and replace in, may be null
- * @param regex the regular expression to which this string is to be matched
- * @param replacement the string to be substituted for the first match
- * @return the text with the first replacement processed,
- * {@code null} if null String input
- *
- * @throws java.util.regex.PatternSyntaxException
- * if the regular expression's syntax is invalid
- *
- * @see String#replaceFirst(String, String)
- * @see Pattern
- * @see Pattern#DOTALL
- * @since 3.5
- *
- * @deprecated Moved to RegExUtils.
- */
- @Deprecated
- public static String replaceFirst(final String text, final String regex, final String replacement) {
- return RegExUtils.replaceFirst(text, regex, replacement);
- }
-
- /**
- * Replaces all occurrences of a String within another String.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replace(null, *, *) = null
- * StringUtils.replace("", *, *) = ""
- * StringUtils.replace("any", null, *) = "any"
- * StringUtils.replace("any", *, null) = "any"
- * StringUtils.replace("any", "", *) = "any"
- * StringUtils.replace("aba", "a", null) = "aba"
- * StringUtils.replace("aba", "a", "") = "b"
- * StringUtils.replace("aba", "a", "z") = "zbz"
- *
- *
- * @see #replace(String text, String searchString, String replacement, int max)
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for, may be null
- * @param replacement the String to replace it with, may be null
- * @return the text with any replacements processed,
- * {@code null} if null String input
- */
- public static String replace(final String text, final String searchString, final String replacement) {
- return replace(text, searchString, replacement, -1);
- }
-
- /**
- * Case insensitively replaces all occurrences of a String within another String.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceIgnoreCase(null, *, *) = null
- * StringUtils.replaceIgnoreCase("", *, *) = ""
- * StringUtils.replaceIgnoreCase("any", null, *) = "any"
- * StringUtils.replaceIgnoreCase("any", *, null) = "any"
- * StringUtils.replaceIgnoreCase("any", "", *) = "any"
- * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba"
- * StringUtils.replaceIgnoreCase("abA", "A", "") = "b"
- * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz"
- *
- *
- * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for (case insensitive), may be null
- * @param replacement the String to replace it with, may be null
- * @return the text with any replacements processed,
- * {@code null} if null String input
- * @since 3.5
- */
- public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
- return replaceIgnoreCase(text, searchString, replacement, -1);
- }
-
- /**
- * Replaces a String with another String inside a larger String,
- * for the first {@code max} values of the search String.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replace(null, *, *, *) = null
- * StringUtils.replace("", *, *, *) = ""
- * StringUtils.replace("any", null, *, *) = "any"
- * StringUtils.replace("any", *, null, *) = "any"
- * StringUtils.replace("any", "", *, *) = "any"
- * StringUtils.replace("any", *, *, 0) = "any"
- * StringUtils.replace("abaa", "a", null, -1) = "abaa"
- * StringUtils.replace("abaa", "a", "", -1) = "b"
- * StringUtils.replace("abaa", "a", "z", 0) = "abaa"
- * StringUtils.replace("abaa", "a", "z", 1) = "zbaa"
- * StringUtils.replace("abaa", "a", "z", 2) = "zbza"
- * StringUtils.replace("abaa", "a", "z", -1) = "zbzz"
- *
- *
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for, may be null
- * @param replacement the String to replace it with, may be null
- * @param max maximum number of values to replace, or {@code -1} if no maximum
- * @return the text with any replacements processed,
- * {@code null} if null String input
- */
- public static String replace(final String text, final String searchString, final String replacement, final int max) {
- return replace(text, searchString, replacement, max, false);
- }
-
- /**
- * Replaces a String with another String inside a larger String,
- * for the first {@code max} values of the search String,
- * case sensitively/insensisitively based on {@code ignoreCase} value.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replace(null, *, *, *, false) = null
- * StringUtils.replace("", *, *, *, false) = ""
- * StringUtils.replace("any", null, *, *, false) = "any"
- * StringUtils.replace("any", *, null, *, false) = "any"
- * StringUtils.replace("any", "", *, *, false) = "any"
- * StringUtils.replace("any", *, *, 0, false) = "any"
- * StringUtils.replace("abaa", "a", null, -1, false) = "abaa"
- * StringUtils.replace("abaa", "a", "", -1, false) = "b"
- * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa"
- * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa"
- * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa"
- * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza"
- * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz"
- *
- *
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for (case insensitive), may be null
- * @param replacement the String to replace it with, may be null
- * @param max maximum number of values to replace, or {@code -1} if no maximum
- * @param ignoreCase if true replace is case insensitive, otherwise case sensitive
- * @return the text with any replacements processed,
- * {@code null} if null String input
- */
- private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) {
- if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
- return text;
- }
- String searchText = text;
- if (ignoreCase) {
- searchText = text.toLowerCase();
- searchString = searchString.toLowerCase();
- }
- int start = 0;
- int end = searchText.indexOf(searchString, start);
- if (end == INDEX_NOT_FOUND) {
- return text;
- }
- final int replLength = searchString.length();
- int increase = replacement.length() - replLength;
- increase = increase < 0 ? 0 : increase;
- increase *= max < 0 ? 16 : max > 64 ? 64 : max;
- final StringBuilder buf = new StringBuilder(text.length() + increase);
- while (end != INDEX_NOT_FOUND) {
- buf.append(text, start, end).append(replacement);
- start = end + replLength;
- if (--max == 0) {
- break;
- }
- end = searchText.indexOf(searchString, start);
- }
- buf.append(text, start, text.length());
- return buf.toString();
- }
-
- /**
- * Case insensitively replaces a String with another String inside a larger String,
- * for the first {@code max} values of the search String.
- *
- * A {@code null} reference passed to this method is a no-op.
- *
- *
- * StringUtils.replaceIgnoreCase(null, *, *, *) = null
- * StringUtils.replaceIgnoreCase("", *, *, *) = ""
- * StringUtils.replaceIgnoreCase("any", null, *, *) = "any"
- * StringUtils.replaceIgnoreCase("any", *, null, *) = "any"
- * StringUtils.replaceIgnoreCase("any", "", *, *) = "any"
- * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any"
- * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
- * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b"
- * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa"
- * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa"
- * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza"
- * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz"
- *
- *
- * @param text text to search and replace in, may be null
- * @param searchString the String to search for (case insensitive), may be null
- * @param replacement the String to replace it with, may be null
- * @param max maximum number of values to replace, or {@code -1} if no maximum
- * @return the text with any replacements processed,
- * {@code null} if null String input
- * @since 3.5
- */
- public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
- return replace(text, searchString, replacement, max, true);
- }
-
- /**
- *
- * Replaces all occurrences of Strings within another String.
- *
- *
- *
- * A {@code null} reference passed to this method is a no-op, or if
- * any "search string" or "string to replace" is null, that replace will be
- * ignored. This will not repeat. For repeating replaces, call the
- * overloaded method.
- *
- *
- *
- * StringUtils.replaceEach(null, *, *) = null
- * StringUtils.replaceEach("", *, *) = ""
- * StringUtils.replaceEach("aba", null, null) = "aba"
- * StringUtils.replaceEach("aba", new String[0], null) = "aba"
- * StringUtils.replaceEach("aba", null, new String[0]) = "aba"
- * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba"
- * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b"
- * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba"
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
- * (example of how it does not repeat)
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
- *
- *
- * @param text
- * text to search and replace in, no-op if null
- * @param searchList
- * the Strings to search for, no-op if null
- * @param replacementList
- * the Strings to replace them with, no-op if null
- * @return the text with any replacements processed, {@code null} if
- * null String input
- * @throws IllegalArgumentException
- * if the lengths of the arrays are not the same (null is ok,
- * and/or size 0)
- * @since 2.4
- */
- public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
- return replaceEach(text, searchList, replacementList, false, 0);
- }
-
- /**
- *
- * Replaces all occurrences of Strings within another String.
- *
- *
- *
- * A {@code null} reference passed to this method is a no-op, or if
- * any "search string" or "string to replace" is null, that replace will be
- * ignored.
- *
- *
- *
- * StringUtils.replaceEachRepeatedly(null, *, *) = null
- * StringUtils.replaceEachRepeatedly("", *, *) = ""
- * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
- * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
- * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
- * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
- * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
- * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
- * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
- * (example of how it repeats)
- * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
- * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
- *
- *
- * @param text
- * text to search and replace in, no-op if null
- * @param searchList
- * the Strings to search for, no-op if null
- * @param replacementList
- * the Strings to replace them with, no-op if null
- * @return the text with any replacements processed, {@code null} if
- * null String input
- * @throws IllegalStateException
- * if the search is repeating and there is an endless loop due
- * to outputs of one being inputs to another
- * @throws IllegalArgumentException
- * if the lengths of the arrays are not the same (null is ok,
- * and/or size 0)
- * @since 2.4
- */
- public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
- // timeToLive should be 0 if not used or nothing to replace, else it's
- // the length of the replace array
- final int timeToLive = searchList == null ? 0 : searchList.length;
- return replaceEach(text, searchList, replacementList, true, timeToLive);
- }
-
- /**
- *
- * Replace all occurrences of Strings within another String.
- * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
- * {@link #replaceEach(String, String[], String[])}
- *
- *
- *
- * A {@code null} reference passed to this method is a no-op, or if
- * any "search string" or "string to replace" is null, that replace will be
- * ignored.
- *
- *
- *
- * StringUtils.replaceEach(null, *, *, *, *) = null
- * StringUtils.replaceEach("", *, *, *, *) = ""
- * StringUtils.replaceEach("aba", null, null, *, *) = "aba"
- * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
- * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
- * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
- * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
- * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
- * (example of how it repeats)
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
- * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
- *
- *
- * @param text
- * text to search and replace in, no-op if null
- * @param searchList
- * the Strings to search for, no-op if null
- * @param replacementList
- * the Strings to replace them with, no-op if null
- * @param repeat if true, then replace repeatedly
- * until there are no more possible replacements or timeToLive < 0
- * @param timeToLive
- * if less than 0 then there is a circular reference and endless
- * loop
- * @return the text with any replacements processed, {@code null} if
- * null String input
- * @throws IllegalStateException
- * if the search is repeating and there is an endless loop due
- * to outputs of one being inputs to another
- * @throws IllegalArgumentException
- * if the lengths of the arrays are not the same (null is ok,
- * and/or size 0)
- * @since 2.4
- */
- private static String replaceEach(
- final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {
-
- // mchyzer Performance note: This creates very few new objects (one major goal)
- // let me know if there are performance requests, we can create a harness to measure
-
- if (text == null || text.isEmpty() || searchList == null ||
- searchList.length == 0 || replacementList == null || replacementList.length == 0) {
- return text;
- }
-
- // if recursing, this shouldn't be less than 0
- if (timeToLive < 0) {
- throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
- "output of one loop is the input of another");
- }
-
- final int searchLength = searchList.length;
- final int replacementLength = replacementList.length;
-
- // make sure lengths are ok, these need to be equal
- if (searchLength != replacementLength) {
- throw new IllegalArgumentException("Search and Replace array lengths don't match: "
- + searchLength
- + " vs "
- + replacementLength);
- }
-
- // keep track of which still have matches
- final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
-
- // index on index that the match was found
- int textIndex = -1;
- int replaceIndex = -1;
- int tempIndex = -1;
-
- // index of replace array that will replace the search string found
- // NOTE: logic duplicated below START
- for (int i = 0; i < searchLength; i++) {
- if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
- searchList[i].isEmpty() || replacementList[i] == null) {
- continue;
- }
- tempIndex = text.indexOf(searchList[i]);
-
- // see if we need to keep searching for this
- if (tempIndex == -1) {
- noMoreMatchesForReplIndex[i] = true;
- } else {
- if (textIndex == -1 || tempIndex < textIndex) {
- textIndex = tempIndex;
- replaceIndex = i;
- }
- }
- }
- // NOTE: logic mostly below END
-
- // no search strings found, we are done
- if (textIndex == -1) {
- return text;
- }
-
- int start = 0;
-
- // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
- int increase = 0;
-
- // count the replacement text elements that are larger than their corresponding text being replaced
- for (int i = 0; i < searchList.length; i++) {
- if (searchList[i] == null || replacementList[i] == null) {
- continue;
- }
- final int greater = replacementList[i].length() - searchList[i].length();
- if (greater > 0) {
- increase += 3 * greater; // assume 3 matches
- }
- }
- // have upper-bound at 20% increase, then let Java take over
- increase = Math.min(increase, text.length() / 5);
-
- final StringBuilder buf = new StringBuilder(text.length() + increase);
-
- while (textIndex != -1) {
-
- for (int i = start; i < textIndex; i++) {
- buf.append(text.charAt(i));
- }
- buf.append(replacementList[replaceIndex]);
-
- start = textIndex + searchList[replaceIndex].length();
-
- textIndex = -1;
- replaceIndex = -1;
- tempIndex = -1;
- // find the next earliest match
- // NOTE: logic mostly duplicated above START
- for (int i = 0; i < searchLength; i++) {
- if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
- searchList[i].isEmpty() || replacementList[i] == null) {
- continue;
- }
- tempIndex = text.indexOf(searchList[i], start);
-
- // see if we need to keep searching for this
- if (tempIndex == -1) {
- noMoreMatchesForReplIndex[i] = true;
- } else {
- if (textIndex == -1 || tempIndex < textIndex) {
- textIndex = tempIndex;
- replaceIndex = i;
- }
- }
- }
- // NOTE: logic duplicated above END
-
- }
- final int textLength = text.length();
- for (int i = start; i < textLength; i++) {
- buf.append(text.charAt(i));
- }
- final String result = buf.toString();
- if (!repeat) {
- return result;
- }
-
- return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
- }
-
- // Replace, character based
- //-----------------------------------------------------------------------
- /**
- * Replaces all occurrences of a character in a String with another.
- * This is a null-safe version of {@link String#replace(char, char)}.
- *
- * A {@code null} string input returns {@code null}.
- * An empty ("") string input returns an empty string.
- *
- *
- * StringUtils.replaceChars(null, *, *) = null
- * StringUtils.replaceChars("", *, *) = ""
- * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
- * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
- *
- *
- * @param str String to replace characters in, may be null
- * @param searchChar the character to search for, may be null
- * @param replaceChar the character to replace, may be null
- * @return modified String, {@code null} if null string input
- * @since 2.0
- */
- public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
- if (str == null) {
- return null;
- }
- return str.replace(searchChar, replaceChar);
- }
-
- /**
- * Replaces multiple characters in a String in one go.
- * This method can also be used to delete characters.
- *
- * For example:
- * replaceChars("hello", "ho", "jy") = jelly.
- *
- * A {@code null} string input returns {@code null}.
- * An empty ("") string input returns an empty string.
- * A null or empty set of search characters returns the input string.
- *
- * The length of the search characters should normally equal the length
- * of the replace characters.
- * If the search characters is longer, then the extra search characters
- * are deleted.
- * If the search characters is shorter, then the extra replace characters
- * are ignored.
- *
- *
- * StringUtils.replaceChars(null, *, *) = null
- * StringUtils.replaceChars("", *, *) = ""
- * StringUtils.replaceChars("abc", null, *) = "abc"
- * StringUtils.replaceChars("abc", "", *) = "abc"
- * StringUtils.replaceChars("abc", "b", null) = "ac"
- * StringUtils.replaceChars("abc", "b", "") = "ac"
- * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya"
- * StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
- * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
- *
- *
- * @param str String to replace characters in, may be null
- * @param searchChars a set of characters to search for, may be null
- * @param replaceChars a set of characters to replace, may be null
- * @return modified String, {@code null} if null string input
- * @since 2.0
- */
- public static String replaceChars(final String str, final String searchChars, String replaceChars) {
- if (isEmpty(str) || isEmpty(searchChars)) {
- return str;
- }
- if (replaceChars == null) {
- replaceChars = EMPTY;
- }
- boolean modified = false;
- final int replaceCharsLength = replaceChars.length();
- final int strLength = str.length();
- final StringBuilder buf = new StringBuilder(strLength);
- for (int i = 0; i < strLength; i++) {
- final char ch = str.charAt(i);
- final int index = searchChars.indexOf(ch);
- if (index >= 0) {
- modified = true;
- if (index < replaceCharsLength) {
- buf.append(replaceChars.charAt(index));
- }
- } else {
- buf.append(ch);
- }
- }
- if (modified) {
- return buf.toString();
- }
- return str;
- }
-
- // Overlay
- //-----------------------------------------------------------------------
- /**
- * Overlays part of a String with another String.
- *
- * A {@code null} string input returns {@code null}.
- * A negative index is treated as zero.
- * An index greater than the string length is treated as the string length.
- * The start index is always the smaller of the two indices.
- *
- *
- * StringUtils.overlay(null, *, *, *) = null
- * StringUtils.overlay("", "abc", 0, 0) = "abc"
- * StringUtils.overlay("abcdef", null, 2, 4) = "abef"
- * StringUtils.overlay("abcdef", "", 2, 4) = "abef"
- * StringUtils.overlay("abcdef", "", 4, 2) = "abef"
- * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef"
- * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef"
- * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef"
- * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz"
- * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
- * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz"
- *
- *
- * @param str the String to do overlaying in, may be null
- * @param overlay the String to overlay, may be null
- * @param start the position to start overlaying at
- * @param end the position to stop overlaying before
- * @return overlayed String, {@code null} if null String input
- * @since 2.0
- */
- public static String overlay(final String str, String overlay, int start, int end) {
- if (str == null) {
- return null;
- }
- if (overlay == null) {
- overlay = EMPTY;
- }
- final int len = str.length();
- if (start < 0) {
- start = 0;
- }
- if (start > len) {
- start = len;
- }
- if (end < 0) {
- end = 0;
- }
- if (end > len) {
- end = len;
- }
- if (start > end) {
- final int temp = start;
- start = end;
- end = temp;
- }
- return str.substring(0, start) +
- overlay +
- str.substring(end);
- }
-
- // Chomping
- //-----------------------------------------------------------------------
- /**
- * Removes one newline from end of a String if it's there,
- * otherwise leave it alone. A newline is "{@code \n}",
- * "{@code \r}", or "{@code \r\n}".
- *
- * NOTE: This method changed in 2.0.
- * It now more closely matches Perl chomp.
- *
- *
- * StringUtils.chomp(null) = null
- * StringUtils.chomp("") = ""
- * StringUtils.chomp("abc \r") = "abc "
- * StringUtils.chomp("abc\n") = "abc"
- * StringUtils.chomp("abc\r\n") = "abc"
- * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
- * StringUtils.chomp("abc\n\r") = "abc\n"
- * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc"
- * StringUtils.chomp("\r") = ""
- * StringUtils.chomp("\n") = ""
- * StringUtils.chomp("\r\n") = ""
- *
- *
- * @param str the String to chomp a newline from, may be null
- * @return String without newline, {@code null} if null String input
- */
- public static String chomp(final String str) {
- if (isEmpty(str)) {
- return str;
- }
-
- if (str.length() == 1) {
- final char ch = str.charAt(0);
- if (ch == CharUtils.CR || ch == CharUtils.LF) {
- return EMPTY;
- }
- return str;
- }
-
- int lastIdx = str.length() - 1;
- final char last = str.charAt(lastIdx);
-
- if (last == CharUtils.LF) {
- if (str.charAt(lastIdx - 1) == CharUtils.CR) {
- lastIdx--;
- }
- } else if (last != CharUtils.CR) {
- lastIdx++;
- }
- return str.substring(0, lastIdx);
- }
-
- /**
- * Removes {@code separator} from the end of
- * {@code str} if it's there, otherwise leave it alone.
- *
- * NOTE: This method changed in version 2.0.
- * It now more closely matches Perl chomp.
- * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
- * This method uses {@link String#endsWith(String)}.
- *
- *
- * StringUtils.chomp(null, *) = null
- * StringUtils.chomp("", *) = ""
- * StringUtils.chomp("foobar", "bar") = "foo"
- * StringUtils.chomp("foobar", "baz") = "foobar"
- * StringUtils.chomp("foo", "foo") = ""
- * StringUtils.chomp("foo ", "foo") = "foo "
- * StringUtils.chomp(" foo", "foo") = " "
- * StringUtils.chomp("foo", "foooo") = "foo"
- * StringUtils.chomp("foo", "") = "foo"
- * StringUtils.chomp("foo", null) = "foo"
- *
- *
- * @param str the String to chomp from, may be null
- * @param separator separator String, may be null
- * @return String without trailing separator, {@code null} if null String input
- * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead
- */
- @Deprecated
- public static String chomp(final String str, final String separator) {
- return removeEnd(str,separator);
- }
-
- // Chopping
- //-----------------------------------------------------------------------
- /**
- * Remove the last character from a String.
- *
- * If the String ends in {@code \r\n}, then remove both
- * of them.
- *
- *
- * StringUtils.chop(null) = null
- * StringUtils.chop("") = ""
- * StringUtils.chop("abc \r") = "abc "
- * StringUtils.chop("abc\n") = "abc"
- * StringUtils.chop("abc\r\n") = "abc"
- * StringUtils.chop("abc") = "ab"
- * StringUtils.chop("abc\nabc") = "abc\nab"
- * StringUtils.chop("a") = ""
- * StringUtils.chop("\r") = ""
- * StringUtils.chop("\n") = ""
- * StringUtils.chop("\r\n") = ""
- *
- *
- * @param str the String to chop last character from, may be null
- * @return String without last character, {@code null} if null String input
- */
- public static String chop(final String str) {
- if (str == null) {
- return null;
- }
- final int strLen = str.length();
- if (strLen < 2) {
- return EMPTY;
- }
- final int lastIdx = strLen - 1;
- final String ret = str.substring(0, lastIdx);
- final char last = str.charAt(lastIdx);
- if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
- return ret.substring(0, lastIdx - 1);
- }
- return ret;
- }
-
- // Conversion
- //-----------------------------------------------------------------------
-
- // Padding
- //-----------------------------------------------------------------------
- /**
- * Repeat a String {@code repeat} times to form a
- * new String.
- *
- *
- * StringUtils.repeat(null, 2) = null
- * StringUtils.repeat("", 0) = ""
- * StringUtils.repeat("", 2) = ""
- * StringUtils.repeat("a", 3) = "aaa"
- * StringUtils.repeat("ab", 2) = "abab"
- * StringUtils.repeat("a", -2) = ""
- *
- *
- * @param str the String to repeat, may be null
- * @param repeat number of times to repeat str, negative treated as zero
- * @return a new String consisting of the original String repeated,
- * {@code null} if null String input
- */
- public static String repeat(final String str, final int repeat) {
- // Performance tuned for 2.0 (JDK1.4)
-
- if (str == null) {
- return null;
- }
- if (repeat <= 0) {
- return EMPTY;
- }
- final int inputLength = str.length();
- if (repeat == 1 || inputLength == 0) {
- return str;
- }
- if (inputLength == 1 && repeat <= PAD_LIMIT) {
- return repeat(str.charAt(0), repeat);
- }
-
- final int outputLength = inputLength * repeat;
- switch (inputLength) {
- case 1 :
- return repeat(str.charAt(0), repeat);
- case 2 :
- final char ch0 = str.charAt(0);
- final char ch1 = str.charAt(1);
- final char[] output2 = new char[outputLength];
- for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
- output2[i] = ch0;
- output2[i + 1] = ch1;
- }
- return new String(output2);
- default :
- final StringBuilder buf = new StringBuilder(outputLength);
- for (int i = 0; i < repeat; i++) {
- buf.append(str);
- }
- return buf.toString();
- }
- }
-
- /**
- * Repeat a String {@code repeat} times to form a
- * new String, with a String separator injected each time.
- *
- *
- * StringUtils.repeat(null, null, 2) = null
- * StringUtils.repeat(null, "x", 2) = null
- * StringUtils.repeat("", null, 0) = ""
- * StringUtils.repeat("", "", 2) = ""
- * StringUtils.repeat("", "x", 3) = "xxx"
- * StringUtils.repeat("?", ", ", 3) = "?, ?, ?"
- *
- *
- * @param str the String to repeat, may be null
- * @param separator the String to inject, may be null
- * @param repeat number of times to repeat str, negative treated as zero
- * @return a new String consisting of the original String repeated,
- * {@code null} if null String input
- * @since 2.5
- */
- public static String repeat(final String str, final String separator, final int repeat) {
- if(str == null || separator == null) {
- return repeat(str, repeat);
- }
- // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
- final String result = repeat(str + separator, repeat);
- return removeEnd(result, separator);
- }
-
- /**
- * Returns padding using the specified delimiter repeated
- * to a given length.
- *
- *
- * StringUtils.repeat('e', 0) = ""
- * StringUtils.repeat('e', 3) = "eee"
- * StringUtils.repeat('e', -2) = ""
- *
- *
- * Note: this method does not support padding with
- * Unicode Supplementary Characters
- * as they require a pair of {@code char}s to be represented.
- * If you are needing to support full I18N of your applications
- * consider using {@link #repeat(String, int)} instead.
- *
- *
- * @param ch character to repeat
- * @param repeat number of times to repeat char, negative treated as zero
- * @return String with repeated character
- * @see #repeat(String, int)
- */
- public static String repeat(final char ch, final int repeat) {
- if (repeat <= 0) {
- return EMPTY;
- }
- final char[] buf = new char[repeat];
- for (int i = repeat - 1; i >= 0; i--) {
- buf[i] = ch;
- }
- return new String(buf);
- }
-
- /**
- * Right pad a String with spaces (' ').
- *
- * The String is padded to the size of {@code size}.
- *
- *
- * StringUtils.rightPad(null, *) = null
- * StringUtils.rightPad("", 3) = " "
- * StringUtils.rightPad("bat", 3) = "bat"
- * StringUtils.rightPad("bat", 5) = "bat "
- * StringUtils.rightPad("bat", 1) = "bat"
- * StringUtils.rightPad("bat", -1) = "bat"
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @return right padded String or original String if no padding is necessary,
- * {@code null} if null String input
- */
- public static String rightPad(final String str, final int size) {
- return rightPad(str, size, ' ');
- }
-
- /**
- * Right pad a String with a specified character.
- *
- * The String is padded to the size of {@code size}.
- *
- *
- * StringUtils.rightPad(null, *, *) = null
- * StringUtils.rightPad("", 3, 'z') = "zzz"
- * StringUtils.rightPad("bat", 3, 'z') = "bat"
- * StringUtils.rightPad("bat", 5, 'z') = "batzz"
- * StringUtils.rightPad("bat", 1, 'z') = "bat"
- * StringUtils.rightPad("bat", -1, 'z') = "bat"
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @param padChar the character to pad with
- * @return right padded String or original String if no padding is necessary,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String rightPad(final String str, final int size, final char padChar) {
- if (str == null) {
- return null;
- }
- final int pads = size - str.length();
- if (pads <= 0) {
- return str; // returns original String when possible
- }
- if (pads > PAD_LIMIT) {
- return rightPad(str, size, String.valueOf(padChar));
- }
- return str.concat(repeat(padChar, pads));
- }
-
- /**
- * Right pad a String with a specified String.
- *
- * The String is padded to the size of {@code size}.
- *
- *
- * StringUtils.rightPad(null, *, *) = null
- * StringUtils.rightPad("", 3, "z") = "zzz"
- * StringUtils.rightPad("bat", 3, "yz") = "bat"
- * StringUtils.rightPad("bat", 5, "yz") = "batyz"
- * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy"
- * StringUtils.rightPad("bat", 1, "yz") = "bat"
- * StringUtils.rightPad("bat", -1, "yz") = "bat"
- * StringUtils.rightPad("bat", 5, null) = "bat "
- * StringUtils.rightPad("bat", 5, "") = "bat "
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @param padStr the String to pad with, null or empty treated as single space
- * @return right padded String or original String if no padding is necessary,
- * {@code null} if null String input
- */
- public static String rightPad(final String str, final int size, String padStr) {
- if (str == null) {
- return null;
- }
- if (isEmpty(padStr)) {
- padStr = SPACE;
- }
- final int padLen = padStr.length();
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str; // returns original String when possible
- }
- if (padLen == 1 && pads <= PAD_LIMIT) {
- return rightPad(str, size, padStr.charAt(0));
- }
-
- if (pads == padLen) {
- return str.concat(padStr);
- } else if (pads < padLen) {
- return str.concat(padStr.substring(0, pads));
- } else {
- final char[] padding = new char[pads];
- final char[] padChars = padStr.toCharArray();
- for (int i = 0; i < pads; i++) {
- padding[i] = padChars[i % padLen];
- }
- return str.concat(new String(padding));
- }
- }
-
- /**
- * Left pad a String with spaces (' ').
- *
- * The String is padded to the size of {@code size}.
- *
- *
- * StringUtils.leftPad(null, *) = null
- * StringUtils.leftPad("", 3) = " "
- * StringUtils.leftPad("bat", 3) = "bat"
- * StringUtils.leftPad("bat", 5) = " bat"
- * StringUtils.leftPad("bat", 1) = "bat"
- * StringUtils.leftPad("bat", -1) = "bat"
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @return left padded String or original String if no padding is necessary,
- * {@code null} if null String input
- */
- public static String leftPad(final String str, final int size) {
- return leftPad(str, size, ' ');
- }
-
- /**
- * Left pad a String with a specified character.
- *
- * Pad to a size of {@code size}.
- *
- *
- * StringUtils.leftPad(null, *, *) = null
- * StringUtils.leftPad("", 3, 'z') = "zzz"
- * StringUtils.leftPad("bat", 3, 'z') = "bat"
- * StringUtils.leftPad("bat", 5, 'z') = "zzbat"
- * StringUtils.leftPad("bat", 1, 'z') = "bat"
- * StringUtils.leftPad("bat", -1, 'z') = "bat"
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @param padChar the character to pad with
- * @return left padded String or original String if no padding is necessary,
- * {@code null} if null String input
- * @since 2.0
- */
- public static String leftPad(final String str, final int size, final char padChar) {
- if (str == null) {
- return null;
- }
- final int pads = size - str.length();
- if (pads <= 0) {
- return str; // returns original String when possible
- }
- if (pads > PAD_LIMIT) {
- return leftPad(str, size, String.valueOf(padChar));
- }
- return repeat(padChar, pads).concat(str);
- }
-
- /**
- * Left pad a String with a specified String.
- *
- * Pad to a size of {@code size}.
- *
- *
- * StringUtils.leftPad(null, *, *) = null
- * StringUtils.leftPad("", 3, "z") = "zzz"
- * StringUtils.leftPad("bat", 3, "yz") = "bat"
- * StringUtils.leftPad("bat", 5, "yz") = "yzbat"
- * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat"
- * StringUtils.leftPad("bat", 1, "yz") = "bat"
- * StringUtils.leftPad("bat", -1, "yz") = "bat"
- * StringUtils.leftPad("bat", 5, null) = " bat"
- * StringUtils.leftPad("bat", 5, "") = " bat"
- *
- *
- * @param str the String to pad out, may be null
- * @param size the size to pad to
- * @param padStr the String to pad with, null or empty treated as single space
- * @return left padded String or original String if no padding is necessary,
- * {@code null} if null String input
- */
- public static String leftPad(final String str, final int size, String padStr) {
- if (str == null) {
- return null;
- }
- if (isEmpty(padStr)) {
- padStr = SPACE;
- }
- final int padLen = padStr.length();
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str; // returns original String when possible
- }
- if (padLen == 1 && pads <= PAD_LIMIT) {
- return leftPad(str, size, padStr.charAt(0));
- }
-
- if (pads == padLen) {
- return padStr.concat(str);
- } else if (pads < padLen) {
- return padStr.substring(0, pads).concat(str);
- } else {
- final char[] padding = new char[pads];
- final char[] padChars = padStr.toCharArray();
- for (int i = 0; i < pads; i++) {
- padding[i] = padChars[i % padLen];
- }
- return new String(padding).concat(str);
- }
- }
-
- /**
- * Gets a CharSequence length or {@code 0} if the CharSequence is
- * {@code null}.
- *
- * @param cs
- * a CharSequence or {@code null}
- * @return CharSequence length or {@code 0} if the CharSequence is
- * {@code null}.
- * @since 2.4
- * @since 3.0 Changed signature from length(String) to length(CharSequence)
- */
- public static int length(final CharSequence cs) {
- return cs == null ? 0 : cs.length();
- }
-
- // Centering
- //-----------------------------------------------------------------------
- /**
- * Centers a String in a larger String of size {@code size}
- * using the space character (' ').
- *
- * If the size is less than the String length, the String is returned.
- * A {@code null} String returns {@code null}.
- * A negative size is treated as zero.
- *
- * Equivalent to {@code center(str, size, " ")}.
- *
- *
- * StringUtils.center(null, *) = null
- * StringUtils.center("", 4) = " "
- * StringUtils.center("ab", -1) = "ab"
- * StringUtils.center("ab", 4) = " ab "
- * StringUtils.center("abcd", 2) = "abcd"
- * StringUtils.center("a", 4) = " a "
- *
- *
- * @param str the String to center, may be null
- * @param size the int size of new String, negative treated as zero
- * @return centered String, {@code null} if null String input
- */
- public static String center(final String str, final int size) {
- return center(str, size, ' ');
- }
-
- /**
- * Centers a String in a larger String of size {@code size}.
- * Uses a supplied character as the value to pad the String with.
- *
- * If the size is less than the String length, the String is returned.
- * A {@code null} String returns {@code null}.
- * A negative size is treated as zero.
- *
- *
- * StringUtils.center(null, *, *) = null
- * StringUtils.center("", 4, ' ') = " "
- * StringUtils.center("ab", -1, ' ') = "ab"
- * StringUtils.center("ab", 4, ' ') = " ab "
- * StringUtils.center("abcd", 2, ' ') = "abcd"
- * StringUtils.center("a", 4, ' ') = " a "
- * StringUtils.center("a", 4, 'y') = "yayy"
- *
- *
- * @param str the String to center, may be null
- * @param size the int size of new String, negative treated as zero
- * @param padChar the character to pad the new String with
- * @return centered String, {@code null} if null String input
- * @since 2.0
- */
- public static String center(String str, final int size, final char padChar) {
- if (str == null || size <= 0) {
- return str;
- }
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str;
- }
- str = leftPad(str, strLen + pads / 2, padChar);
- str = rightPad(str, size, padChar);
- return str;
- }
-
- /**
- * Centers a String in a larger String of size {@code size}.
- * Uses a supplied String as the value to pad the String with.
- *
- * If the size is less than the String length, the String is returned.
- * A {@code null} String returns {@code null}.
- * A negative size is treated as zero.
- *
- *
- * StringUtils.center(null, *, *) = null
- * StringUtils.center("", 4, " ") = " "
- * StringUtils.center("ab", -1, " ") = "ab"
- * StringUtils.center("ab", 4, " ") = " ab "
- * StringUtils.center("abcd", 2, " ") = "abcd"
- * StringUtils.center("a", 4, " ") = " a "
- * StringUtils.center("a", 4, "yz") = "yayz"
- * StringUtils.center("abc", 7, null) = " abc "
- * StringUtils.center("abc", 7, "") = " abc "
- *
- *
- * @param str the String to center, may be null
- * @param size the int size of new String, negative treated as zero
- * @param padStr the String to pad the new String with, must not be null or empty
- * @return centered String, {@code null} if null String input
- * @throws IllegalArgumentException if padStr is {@code null} or empty
- */
- public static String center(String str, final int size, String padStr) {
- if (str == null || size <= 0) {
- return str;
- }
- if (isEmpty(padStr)) {
- padStr = SPACE;
- }
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str;
- }
- str = leftPad(str, strLen + pads / 2, padStr);
- str = rightPad(str, size, padStr);
- return str;
- }
-
- // Case conversion
- //-----------------------------------------------------------------------
- /**
- * Converts a String to upper case as per {@link String#toUpperCase()}.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.upperCase(null) = null
- * StringUtils.upperCase("") = ""
- * StringUtils.upperCase("aBc") = "ABC"
- *
- *
- * Note: As described in the documentation for {@link String#toUpperCase()},
- * the result of this method is affected by the current locale.
- * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
- * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
- *
- * @param str the String to upper case, may be null
- * @return the upper cased String, {@code null} if null String input
- */
- public static String upperCase(final String str) {
- if (str == null) {
- return null;
- }
- return str.toUpperCase();
- }
-
- /**
- * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.upperCase(null, Locale.ENGLISH) = null
- * StringUtils.upperCase("", Locale.ENGLISH) = ""
- * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
- *
- *
- * @param str the String to upper case, may be null
- * @param locale the locale that defines the case transformation rules, must not be null
- * @return the upper cased String, {@code null} if null String input
- * @since 2.5
- */
- public static String upperCase(final String str, final Locale locale) {
- if (str == null) {
- return null;
- }
- return str.toUpperCase(locale);
- }
-
- /**
- * Converts a String to lower case as per {@link String#toLowerCase()}.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.lowerCase(null) = null
- * StringUtils.lowerCase("") = ""
- * StringUtils.lowerCase("aBc") = "abc"
- *
- *
- * Note: As described in the documentation for {@link String#toLowerCase()},
- * the result of this method is affected by the current locale.
- * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
- * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
- *
- * @param str the String to lower case, may be null
- * @return the lower cased String, {@code null} if null String input
- */
- public static String lowerCase(final String str) {
- if (str == null) {
- return null;
- }
- return str.toLowerCase();
- }
-
- /**
- * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.lowerCase(null, Locale.ENGLISH) = null
- * StringUtils.lowerCase("", Locale.ENGLISH) = ""
- * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
- *
- *
- * @param str the String to lower case, may be null
- * @param locale the locale that defines the case transformation rules, must not be null
- * @return the lower cased String, {@code null} if null String input
- * @since 2.5
- */
- public static String lowerCase(final String str, final Locale locale) {
- if (str == null) {
- return null;
- }
- return str.toLowerCase(locale);
- }
-
- /**
- * Capitalizes a String changing the first character to title case as
- * per {@link Character#toTitleCase(int)}. No other characters are changed.
- *
- * For a word based algorithm, see {@link .text.WordUtils#capitalize(String)}.
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.capitalize(null) = null
- * StringUtils.capitalize("") = ""
- * StringUtils.capitalize("cat") = "Cat"
- * StringUtils.capitalize("cAt") = "CAt"
- * StringUtils.capitalize("'cat'") = "'cat'"
- *
- *
- * @param str the String to capitalize, may be null
- * @return the capitalized String, {@code null} if null String input
- * @see .text.WordUtils#capitalize(String)
- * @see #uncapitalize(String)
- * @since 2.0
- */
- public static String capitalize(final String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
- return str;
- }
-
- final int firstCodepoint = str.codePointAt(0);
- final int newCodePoint = Character.toTitleCase(firstCodepoint);
- if (firstCodepoint == newCodePoint) {
- // already capitalized
- return str;
- }
-
- final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
- int outOffset = 0;
- newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
- for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
- final int codepoint = str.codePointAt(inOffset);
- newCodePoints[outOffset++] = codepoint; // copy the remaining ones
- inOffset += Character.charCount(codepoint);
- }
- return new String(newCodePoints, 0, outOffset);
- }
-
- /**
- * Uncapitalizes a String, changing the first character to lower case as
- * per {@link Character#toLowerCase(int)}. No other characters are changed.
- *
- * For a word based algorithm, see {@link .text.WordUtils#uncapitalize(String)}.
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.uncapitalize(null) = null
- * StringUtils.uncapitalize("") = ""
- * StringUtils.uncapitalize("cat") = "cat"
- * StringUtils.uncapitalize("Cat") = "cat"
- * StringUtils.uncapitalize("CAT") = "cAT"
- *
- *
- * @param str the String to uncapitalize, may be null
- * @return the uncapitalized String, {@code null} if null String input
- * @see .text.WordUtils#uncapitalize(String)
- * @see #capitalize(String)
- * @since 2.0
- */
- public static String uncapitalize(final String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
- return str;
- }
-
- final int firstCodepoint = str.codePointAt(0);
- final int newCodePoint = Character.toLowerCase(firstCodepoint);
- if (firstCodepoint == newCodePoint) {
- // already capitalized
- return str;
- }
-
- final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
- int outOffset = 0;
- newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
- for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
- final int codepoint = str.codePointAt(inOffset);
- newCodePoints[outOffset++] = codepoint; // copy the remaining ones
- inOffset += Character.charCount(codepoint);
- }
- return new String(newCodePoints, 0, outOffset);
- }
-
- /**
- * Swaps the case of a String changing upper and title case to
- * lower case, and lower case to upper case.
- *
- *
- * Upper case character converts to Lower case
- * Title case character converts to Lower case
- * Lower case character converts to Upper case
- *
- *
- * For a word based algorithm, see {@link .text.WordUtils#swapCase(String)}.
- * A {@code null} input String returns {@code null}.
- *
- *
- * StringUtils.swapCase(null) = null
- * StringUtils.swapCase("") = ""
- * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
- *
- *
- * NOTE: This method changed in Lang version 2.0.
- * It no longer performs a word based algorithm.
- * If you only use ASCII, you will notice no change.
- * That functionality is available in .text.WordUtils.
- *
- * @param str the String to swap case, may be null
- * @return the changed String, {@code null} if null String input
- */
- public static String swapCase(final String str) {
- if (isEmpty(str)) {
- return str;
- }
-
- final int strLen = str.length();
- final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
- int outOffset = 0;
- for (int i = 0; i < strLen; ) {
- final int oldCodepoint = str.codePointAt(i);
- final int newCodePoint;
- if (Character.isUpperCase(oldCodepoint)) {
- newCodePoint = Character.toLowerCase(oldCodepoint);
- } else if (Character.isTitleCase(oldCodepoint)) {
- newCodePoint = Character.toLowerCase(oldCodepoint);
- } else if (Character.isLowerCase(oldCodepoint)) {
- newCodePoint = Character.toUpperCase(oldCodepoint);
- } else {
- newCodePoint = oldCodepoint;
- }
- newCodePoints[outOffset++] = newCodePoint;
- i += Character.charCount(newCodePoint);
- }
- return new String(newCodePoints, 0, outOffset);
- }
-
- // Count matches
- //-----------------------------------------------------------------------
- /**
- * Counts how many times the substring appears in the larger string.
- *
- * A {@code null} or empty ("") String input returns {@code 0}.
- *
- *
- * StringUtils.countMatches(null, *) = 0
- * StringUtils.countMatches("", *) = 0
- * StringUtils.countMatches("abba", null) = 0
- * StringUtils.countMatches("abba", "") = 0
- * StringUtils.countMatches("abba", "a") = 2
- * StringUtils.countMatches("abba", "ab") = 1
- * StringUtils.countMatches("abba", "xxx") = 0
- *
- *
- * @param str the CharSequence to check, may be null
- * @param sub the substring to count, may be null
- * @return the number of occurrences, 0 if either CharSequence is {@code null}
- * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
- */
- public static int countMatches(final CharSequence str, final CharSequence sub) {
- if (isEmpty(str) || isEmpty(sub)) {
- return 0;
- }
- int count = 0;
- int idx = 0;
- while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
- count++;
- idx += sub.length();
- }
- return count;
- }
-
- /**
- * Counts how many times the char appears in the given string.
- *
- * A {@code null} or empty ("") String input returns {@code 0}.
- *
- *
- * StringUtils.countMatches(null, *) = 0
- * StringUtils.countMatches("", *) = 0
- * StringUtils.countMatches("abba", 0) = 0
- * StringUtils.countMatches("abba", 'a') = 2
- * StringUtils.countMatches("abba", 'b') = 2
- * StringUtils.countMatches("abba", 'x') = 0
- *
- *
- * @param str the CharSequence to check, may be null
- * @param ch the char to count
- * @return the number of occurrences, 0 if the CharSequence is {@code null}
- * @since 3.4
- */
- public static int countMatches(final CharSequence str, final char ch) {
- if (isEmpty(str)) {
- return 0;
- }
- int count = 0;
- // We could also call str.toCharArray() for faster look ups but that would generate more garbage.
- for (int i = 0; i < str.length(); i++) {
- if (ch == str.charAt(i)) {
- count++;
- }
- }
- return count;
- }
-
- // Character Tests
- //-----------------------------------------------------------------------
- /**
- * Checks if the CharSequence contains only Unicode letters.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code false}.
- *
- *
- * StringUtils.isAlpha(null) = false
- * StringUtils.isAlpha("") = false
- * StringUtils.isAlpha(" ") = false
- * StringUtils.isAlpha("abc") = true
- * StringUtils.isAlpha("ab2c") = false
- * StringUtils.isAlpha("ab-c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains letters, and is non-null
- * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
- * @since 3.0 Changed "" to return false and not true
- */
- public static boolean isAlpha(final CharSequence cs) {
- if (isEmpty(cs)) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isLetter(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only Unicode letters and
- * space (' ').
- *
- * {@code null} will return {@code false}
- * An empty CharSequence (length()=0) will return {@code true}.
- *
- *
- * StringUtils.isAlphaSpace(null) = false
- * StringUtils.isAlphaSpace("") = true
- * StringUtils.isAlphaSpace(" ") = true
- * StringUtils.isAlphaSpace("abc") = true
- * StringUtils.isAlphaSpace("ab c") = true
- * StringUtils.isAlphaSpace("ab2c") = false
- * StringUtils.isAlphaSpace("ab-c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains letters and space,
- * and is non-null
- * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
- */
- public static boolean isAlphaSpace(final CharSequence cs) {
- if (cs == null) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isLetter(cs.charAt(i)) && cs.charAt(i) != ' ') {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only Unicode letters or digits.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code false}.
- *
- *
- * StringUtils.isAlphanumeric(null) = false
- * StringUtils.isAlphanumeric("") = false
- * StringUtils.isAlphanumeric(" ") = false
- * StringUtils.isAlphanumeric("abc") = true
- * StringUtils.isAlphanumeric("ab c") = false
- * StringUtils.isAlphanumeric("ab2c") = true
- * StringUtils.isAlphanumeric("ab-c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains letters or digits,
- * and is non-null
- * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
- * @since 3.0 Changed "" to return false and not true
- */
- public static boolean isAlphanumeric(final CharSequence cs) {
- if (isEmpty(cs)) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isLetterOrDigit(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only Unicode letters, digits
- * or space ({@code ' '}).
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code true}.
- *
- *
- * StringUtils.isAlphanumericSpace(null) = false
- * StringUtils.isAlphanumericSpace("") = true
- * StringUtils.isAlphanumericSpace(" ") = true
- * StringUtils.isAlphanumericSpace("abc") = true
- * StringUtils.isAlphanumericSpace("ab c") = true
- * StringUtils.isAlphanumericSpace("ab2c") = true
- * StringUtils.isAlphanumericSpace("ab-c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains letters, digits or space,
- * and is non-null
- * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
- */
- public static boolean isAlphanumericSpace(final CharSequence cs) {
- if (cs == null) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isLetterOrDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only ASCII printable characters.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code true}.
- *
- *
- * StringUtils.isAsciiPrintable(null) = false
- * StringUtils.isAsciiPrintable("") = true
- * StringUtils.isAsciiPrintable(" ") = true
- * StringUtils.isAsciiPrintable("Ceki") = true
- * StringUtils.isAsciiPrintable("ab2c") = true
- * StringUtils.isAsciiPrintable("!ab-c~") = true
- * StringUtils.isAsciiPrintable("\u0020") = true
- * StringUtils.isAsciiPrintable("\u0021") = true
- * StringUtils.isAsciiPrintable("\u007e") = true
- * StringUtils.isAsciiPrintable("\u007f") = false
- * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if every character is in the range
- * 32 thru 126
- * @since 2.1
- * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
- */
- public static boolean isAsciiPrintable(final CharSequence cs) {
- if (cs == null) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only Unicode digits.
- * A decimal point is not a Unicode digit and returns false.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code false}.
- *
- * Note that the method does not allow for a leading sign, either positive or negative.
- * Also, if a String passes the numeric test, it may still generate a NumberFormatException
- * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
- * for int or long respectively.
- *
- *
- * StringUtils.isNumeric(null) = false
- * StringUtils.isNumeric("") = false
- * StringUtils.isNumeric(" ") = false
- * StringUtils.isNumeric("123") = true
- * StringUtils.isNumeric("\u0967\u0968\u0969") = true
- * StringUtils.isNumeric("12 3") = false
- * StringUtils.isNumeric("ab2c") = false
- * StringUtils.isNumeric("12-3") = false
- * StringUtils.isNumeric("12.3") = false
- * StringUtils.isNumeric("-123") = false
- * StringUtils.isNumeric("+123") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains digits, and is non-null
- * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
- * @since 3.0 Changed "" to return false and not true
- */
- public static boolean isNumeric(final CharSequence cs) {
- if (isEmpty(cs)) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isDigit(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only Unicode digits or space
- * ({@code ' '}).
- * A decimal point is not a Unicode digit and returns false.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code true}.
- *
- *
- * StringUtils.isNumericSpace(null) = false
- * StringUtils.isNumericSpace("") = true
- * StringUtils.isNumericSpace(" ") = true
- * StringUtils.isNumericSpace("123") = true
- * StringUtils.isNumericSpace("12 3") = true
- * StringUtils.isNumeric("\u0967\u0968\u0969") = true
- * StringUtils.isNumeric("\u0967\u0968 \u0969") = true
- * StringUtils.isNumericSpace("ab2c") = false
- * StringUtils.isNumericSpace("12-3") = false
- * StringUtils.isNumericSpace("12.3") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains digits or space,
- * and is non-null
- * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
- */
- public static boolean isNumericSpace(final CharSequence cs) {
- if (cs == null) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if a String {@code str} contains Unicode digits,
- * if yes then concatenate all the digits in {@code str} and return it as a String.
- *
- * An empty ("") String will be returned if no digits found in {@code str}.
- *
- *
- * StringUtils.getDigits(null) = null
- * StringUtils.getDigits("") = ""
- * StringUtils.getDigits("abc") = ""
- * StringUtils.getDigits("1000$") = "1000"
- * StringUtils.getDigits("1123~45") = "112345"
- * StringUtils.getDigits("(541) 754-3010") = "5417543010"
- * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
- *
- *
- * @param str the String to extract digits from, may be null
- * @return String with only digits,
- * or an empty ("") String if no digits found,
- * or {@code null} String if {@code str} is null
- * @since 3.6
- */
- public static String getDigits(final String str) {
- if (isEmpty(str)) {
- return str;
- }
- final int sz = str.length();
- final StringBuilder strDigits = new StringBuilder(sz);
- for (int i = 0; i < sz; i++) {
- final char tempChar = str.charAt(i);
- if (Character.isDigit(tempChar)) {
- strDigits.append(tempChar);
- }
- }
- return strDigits.toString();
- }
-
- /**
- * Checks if the CharSequence contains only whitespace.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code true}.
- *
- *
- * StringUtils.isWhitespace(null) = false
- * StringUtils.isWhitespace("") = true
- * StringUtils.isWhitespace(" ") = true
- * StringUtils.isWhitespace("abc") = false
- * StringUtils.isWhitespace("ab2c") = false
- * StringUtils.isWhitespace("ab-c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains whitespace, and is non-null
- * @since 2.0
- * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
- */
- public static boolean isWhitespace(final CharSequence cs) {
- if (cs == null) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isWhitespace(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only lowercase characters.
- *
- * {@code null} will return {@code false}.
- * An empty CharSequence (length()=0) will return {@code false}.
- *
- *
- * StringUtils.isAllLowerCase(null) = false
- * StringUtils.isAllLowerCase("") = false
- * StringUtils.isAllLowerCase(" ") = false
- * StringUtils.isAllLowerCase("abc") = true
- * StringUtils.isAllLowerCase("abC") = false
- * StringUtils.isAllLowerCase("ab c") = false
- * StringUtils.isAllLowerCase("ab1c") = false
- * StringUtils.isAllLowerCase("ab/c") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains lowercase characters, and is non-null
- * @since 2.5
- * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
- */
- public static boolean isAllLowerCase(final CharSequence cs) {
- if (cs == null || isEmpty(cs)) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isLowerCase(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains only uppercase characters.
- *
- * {@code null} will return {@code false}.
- * An empty String (length()=0) will return {@code false}.
- *
- *
- * StringUtils.isAllUpperCase(null) = false
- * StringUtils.isAllUpperCase("") = false
- * StringUtils.isAllUpperCase(" ") = false
- * StringUtils.isAllUpperCase("ABC") = true
- * StringUtils.isAllUpperCase("aBC") = false
- * StringUtils.isAllUpperCase("A C") = false
- * StringUtils.isAllUpperCase("A1C") = false
- * StringUtils.isAllUpperCase("A/C") = false
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if only contains uppercase characters, and is non-null
- * @since 2.5
- * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
- */
- public static boolean isAllUpperCase(final CharSequence cs) {
- if (cs == null || isEmpty(cs)) {
- return false;
- }
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (!Character.isUpperCase(cs.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.
- *
- * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return
- * {@code false}.
- *
- *
- * StringUtils.isMixedCase(null) = false
- * StringUtils.isMixedCase("") = false
- * StringUtils.isMixedCase("ABC") = false
- * StringUtils.isMixedCase("abc") = false
- * StringUtils.isMixedCase("aBc") = true
- * StringUtils.isMixedCase("A c") = true
- * StringUtils.isMixedCase("A1c") = true
- * StringUtils.isMixedCase("a/C") = true
- * StringUtils.isMixedCase("aC\t") = true
- *
- *
- * @param cs the CharSequence to check, may be null
- * @return {@code true} if the CharSequence contains both uppercase and lowercase characters
- * @since 3.5
- */
- public static boolean isMixedCase(final CharSequence cs) {
- if (isEmpty(cs) || cs.length() == 1) {
- return false;
- }
- boolean containsUppercase = false;
- boolean containsLowercase = false;
- final int sz = cs.length();
- for (int i = 0; i < sz; i++) {
- if (containsUppercase && containsLowercase) {
- return true;
- } else if (Character.isUpperCase(cs.charAt(i))) {
- containsUppercase = true;
- } else if (Character.isLowerCase(cs.charAt(i))) {
- containsLowercase = true;
- }
- }
- return containsUppercase && containsLowercase;
- }
-
- // Defaults
- //-----------------------------------------------------------------------
- /**
- * Returns either the passed in String,
- * or if the String is {@code null}, an empty String ("").
- *
- *
- * StringUtils.defaultString(null) = ""
- * StringUtils.defaultString("") = ""
- * StringUtils.defaultString("bat") = "bat"
- *
- *
- * @see ObjectUtils#toString(Object)
- * @see String#valueOf(Object)
- * @param str the String to check, may be null
- * @return the passed in String, or the empty String if it
- * was {@code null}
- */
- public static String defaultString(final String str) {
- return defaultString(str, EMPTY);
- }
-
- /**
- * Returns either the passed in String, or if the String is
- * {@code null}, the value of {@code defaultStr}.
- *
- *
- * StringUtils.defaultString(null, "NULL") = "NULL"
- * StringUtils.defaultString("", "NULL") = ""
- * StringUtils.defaultString("bat", "NULL") = "bat"
- *
- *
- * @see ObjectUtils#toString(Object,String)
- * @see String#valueOf(Object)
- * @param str the String to check, may be null
- * @param defaultStr the default String to return
- * if the input is {@code null}, may be null
- * @return the passed in String, or the default if it was {@code null}
- */
- public static String defaultString(final String str, final String defaultStr) {
- return str == null ? defaultStr : str;
- }
-
- /**
- * Returns the first value in the array which is not empty (""),
- * {@code null} or whitespace only.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- * If all values are blank or the array is {@code null}
- * or empty then {@code null} is returned.
- *
- *
- * StringUtils.firstNonBlank(null, null, null) = null
- * StringUtils.firstNonBlank(null, "", " ") = null
- * StringUtils.firstNonBlank("abc") = "abc"
- * StringUtils.firstNonBlank(null, "xyz") = "xyz"
- * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
- * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz"
- * StringUtils.firstNonBlank() = null
- *
- *
- * @param the specific kind of CharSequence
- * @param values the values to test, may be {@code null} or empty
- * @return the first value from {@code values} which is not blank,
- * or {@code null} if there are no non-blank values
- * @since 3.8
- */
- @SafeVarargs
- public static T firstNonBlank(final T... values) {
- if (values != null) {
- for (final T val : values) {
- if (isNotBlank(val)) {
- return val;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the first value in the array which is not empty.
- *
- * If all values are empty or the array is {@code null}
- * or empty then {@code null} is returned.
- *
- *
- * StringUtils.firstNonEmpty(null, null, null) = null
- * StringUtils.firstNonEmpty(null, null, "") = null
- * StringUtils.firstNonEmpty(null, "", " ") = " "
- * StringUtils.firstNonEmpty("abc") = "abc"
- * StringUtils.firstNonEmpty(null, "xyz") = "xyz"
- * StringUtils.firstNonEmpty("", "xyz") = "xyz"
- * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
- * StringUtils.firstNonEmpty() = null
- *
- *
- * @param the specific kind of CharSequence
- * @param values the values to test, may be {@code null} or empty
- * @return the first value from {@code values} which is not empty,
- * or {@code null} if there are no non-empty values
- * @since 3.8
- */
- @SafeVarargs
- public static T firstNonEmpty(final T... values) {
- if (values != null) {
- for (final T val : values) {
- if (isNotEmpty(val)) {
- return val;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns either the passed in CharSequence, or if the CharSequence is
- * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.
- *
- * Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
- *
- * StringUtils.defaultIfBlank(null, "NULL") = "NULL"
- * StringUtils.defaultIfBlank("", "NULL") = "NULL"
- * StringUtils.defaultIfBlank(" ", "NULL") = "NULL"
- * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
- * StringUtils.defaultIfBlank("", null) = null
- *
- * @param the specific kind of CharSequence
- * @param str the CharSequence to check, may be null
- * @param defaultStr the default CharSequence to return
- * if the input is whitespace, empty ("") or {@code null}, may be null
- * @return the passed in CharSequence, or the default
- * @see StringUtils#defaultString(String, String)
- */
- public static T defaultIfBlank(final T str, final T defaultStr) {
- return isBlank(str) ? defaultStr : str;
- }
-
- /**
- * Returns either the passed in CharSequence, or if the CharSequence is
- * empty or {@code null}, the value of {@code defaultStr}.
- *
- *
- * StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
- * StringUtils.defaultIfEmpty("", "NULL") = "NULL"
- * StringUtils.defaultIfEmpty(" ", "NULL") = " "
- * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
- * StringUtils.defaultIfEmpty("", null) = null
- *
- * @param the specific kind of CharSequence
- * @param str the CharSequence to check, may be null
- * @param defaultStr the default CharSequence to return
- * if the input is empty ("") or {@code null}, may be null
- * @return the passed in CharSequence, or the default
- * @see StringUtils#defaultString(String, String)
- */
- public static T defaultIfEmpty(final T str, final T defaultStr) {
- return isEmpty(str) ? defaultStr : str;
- }
-
- // Rotating (circular shift)
- //-----------------------------------------------------------------------
- /**
- * Rotate (circular shift) a String of {@code shift} characters.
- *
- * If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)
- * If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)
- *
- *
- *
- * StringUtils.rotate(null, *) = null
- * StringUtils.rotate("", *) = ""
- * StringUtils.rotate("abcdefg", 0) = "abcdefg"
- * StringUtils.rotate("abcdefg", 2) = "fgabcde"
- * StringUtils.rotate("abcdefg", -2) = "cdefgab"
- * StringUtils.rotate("abcdefg", 7) = "abcdefg"
- * StringUtils.rotate("abcdefg", -7) = "abcdefg"
- * StringUtils.rotate("abcdefg", 9) = "fgabcde"
- * StringUtils.rotate("abcdefg", -9) = "cdefgab"
- *
- *
- * @param str the String to rotate, may be null
- * @param shift number of time to shift (positive : right shift, negative : left shift)
- * @return the rotated String,
- * or the original String if {@code shift == 0},
- * or {@code null} if null String input
- * @since 3.5
- */
- public static String rotate(final String str, final int shift) {
- if (str == null) {
- return null;
- }
-
- final int strLen = str.length();
- if (shift == 0 || strLen == 0 || shift % strLen == 0) {
- return str;
- }
-
- final StringBuilder builder = new StringBuilder(strLen);
- final int offset = - (shift % strLen);
- builder.append(substring(str, offset));
- builder.append(substring(str, 0, offset));
- return builder.toString();
- }
-
- // Reversing
- //-----------------------------------------------------------------------
- /**
- * Reverses a String as per {@link StringBuilder#reverse()}.
- *
- * A {@code null} String returns {@code null}.
- *
- *
- * StringUtils.reverse(null) = null
- * StringUtils.reverse("") = ""
- * StringUtils.reverse("bat") = "tab"
- *
- *
- * @param str the String to reverse, may be null
- * @return the reversed String, {@code null} if null String input
- */
- public static String reverse(final String str) {
- if (str == null) {
- return null;
- }
- return new StringBuilder(str).reverse().toString();
- }
-
- /**
- * Reverses a String that is delimited by a specific character.
- *
- * The Strings between the delimiters are not reversed.
- * Thus java.lang.String becomes String.lang.java (if the delimiter
- * is {@code '.'}).
- *
- *
- * StringUtils.reverseDelimited(null, *) = null
- * StringUtils.reverseDelimited("", *) = ""
- * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
- * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
- *
- *
- * @param str the String to reverse, may be null
- * @param separatorChar the separator character to use
- * @return the reversed String, {@code null} if null String input
- * @since 2.0
- */
- public static String reverseDelimited(final String str, final char separatorChar) {
- if (str == null) {
- return null;
- }
- // could implement manually, but simple way is to reuse other,
- // probably slower, methods.
- final String[] strs = split(str, separatorChar);
- ArrayUtils.reverse(strs);
- return join(strs, separatorChar);
- }
-
- // Abbreviating
- //-----------------------------------------------------------------------
- /**
- * Abbreviates a String using ellipses. This will turn
- * "Now is the time for all good men" into "Now is the time for..."
- *
- * Specifically:
- *
- * If the number of characters in {@code str} is less than or equal to
- * {@code maxWidth}, return {@code str}.
- * Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.
- * If {@code maxWidth} is less than {@code 4}, throw an
- * {@code IllegalArgumentException}.
- * In no case will it return a String of length greater than
- * {@code maxWidth}.
- *
- *
- *
- * StringUtils.abbreviate(null, *) = null
- * StringUtils.abbreviate("", 4) = ""
- * StringUtils.abbreviate("abcdefg", 6) = "abc..."
- * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
- * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
- * StringUtils.abbreviate("abcdefg", 4) = "a..."
- * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
- *
- *
- * @param str the String to check, may be null
- * @param maxWidth maximum length of result String, must be at least 4
- * @return abbreviated String, {@code null} if null String input
- * @throws IllegalArgumentException if the width is too small
- * @since 2.0
- */
- public static String abbreviate(final String str, final int maxWidth) {
- final String defaultAbbrevMarker = "...";
- return abbreviate(str, defaultAbbrevMarker, 0, maxWidth);
- }
-
- /**
- * Abbreviates a String using ellipses. This will turn
- * "Now is the time for all good men" into "...is the time for..."
- *
- * Works like {@code abbreviate(String, int)}, but allows you to specify
- * a "left edge" offset. Note that this left edge is not necessarily going to
- * be the leftmost character in the result, or the first character following the
- * ellipses, but it will appear somewhere in the result.
- *
- *
In no case will it return a String of length greater than
- * {@code maxWidth}.
- *
- *
- * StringUtils.abbreviate(null, *, *) = null
- * StringUtils.abbreviate("", 0, 4) = ""
- * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
- * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..."
- * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..."
- * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..."
- * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..."
- * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..."
- * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno"
- * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
- * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
- * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException
- * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException
- *
- *
- * @param str the String to check, may be null
- * @param offset left edge of source String
- * @param maxWidth maximum length of result String, must be at least 4
- * @return abbreviated String, {@code null} if null String input
- * @throws IllegalArgumentException if the width is too small
- * @since 2.0
- */
- public static String abbreviate(final String str, final int offset, final int maxWidth) {
- final String defaultAbbrevMarker = "...";
- return abbreviate(str, defaultAbbrevMarker, offset, maxWidth);
- }
-
- /**
- * Abbreviates a String using another given String as replacement marker. This will turn
- * "Now is the time for all good men" into "Now is the time for..." if "..." was defined
- * as the replacement marker.
- *
- * Specifically:
- *
- * If the number of characters in {@code str} is less than or equal to
- * {@code maxWidth}, return {@code str}.
- * Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.
- * If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an
- * {@code IllegalArgumentException}.
- * In no case will it return a String of length greater than
- * {@code maxWidth}.
- *
- *
- *
- * StringUtils.abbreviate(null, "...", *) = null
- * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg"
- * StringUtils.abbreviate("", "...", 4) = ""
- * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd."
- * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg"
- * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg"
- * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.."
- * StringUtils.abbreviate("abcdefg", "..", 3) = "a.."
- * StringUtils.abbreviate("abcdefg", "..", 2) = IllegalArgumentException
- * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException
- *
- *
- * @param str the String to check, may be null
- * @param abbrevMarker the String used as replacement marker
- * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}
- * @return abbreviated String, {@code null} if null String input
- * @throws IllegalArgumentException if the width is too small
- * @since 3.6
- */
- public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
- return abbreviate(str, abbrevMarker, 0, maxWidth);
- }
-
- /**
- * Abbreviates a String using a given replacement marker. This will turn
- * "Now is the time for all good men" into "...is the time for..." if "..." was defined
- * as the replacement marker.
- *
- * Works like {@code abbreviate(String, String, int)}, but allows you to specify
- * a "left edge" offset. Note that this left edge is not necessarily going to
- * be the leftmost character in the result, or the first character following the
- * replacement marker, but it will appear somewhere in the result.
- *
- *
In no case will it return a String of length greater than {@code maxWidth}.
- *
- *
- * StringUtils.abbreviate(null, null, *, *) = null
- * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno"
- * StringUtils.abbreviate("", "...", 0, 4) = ""
- * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
- * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi,"
- * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi,"
- * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi,"
- * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::"
- * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..."
- * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno"
- * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno"
- * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno"
- * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = IllegalArgumentException
- * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = IllegalArgumentException
- *
- *
- * @param str the String to check, may be null
- * @param abbrevMarker the String used as replacement marker
- * @param offset left edge of source String
- * @param maxWidth maximum length of result String, must be at least 4
- * @return abbreviated String, {@code null} if null String input
- * @throws IllegalArgumentException if the width is too small
- * @since 3.6
- */
- public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) {
- if (isEmpty(str) || isEmpty(abbrevMarker)) {
- return str;
- }
-
- final int abbrevMarkerLength = abbrevMarker.length();
- final int minAbbrevWidth = abbrevMarkerLength + 1;
- final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;
-
- if (maxWidth < minAbbrevWidth) {
- throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
- }
- if (str.length() <= maxWidth) {
- return str;
- }
- if (offset > str.length()) {
- offset = str.length();
- }
- if (str.length() - offset < maxWidth - abbrevMarkerLength) {
- offset = str.length() - (maxWidth - abbrevMarkerLength);
- }
- if (offset <= abbrevMarkerLength+1) {
- return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
- }
- if (maxWidth < minAbbrevWidthOffset) {
- throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
- }
- if (offset + maxWidth - abbrevMarkerLength < str.length()) {
- return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
- }
- return abbrevMarker + str.substring(str.length() - (maxWidth - abbrevMarkerLength));
- }
-
- /**
- * Abbreviates a String to the length passed, replacing the middle characters with the supplied
- * replacement String.
- *
- * This abbreviation only occurs if the following criteria is met:
- *
- * Neither the String for abbreviation nor the replacement String are null or empty
- * The length to truncate to is less than the length of the supplied String
- * The length to truncate to is greater than 0
- * The abbreviated String will have enough room for the length supplied replacement String
- * and the first and last characters of the supplied String for abbreviation
- *
- * Otherwise, the returned String will be the same as the supplied String for abbreviation.
- *
- *
- *
- * StringUtils.abbreviateMiddle(null, null, 0) = null
- * StringUtils.abbreviateMiddle("abc", null, 0) = "abc"
- * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc"
- * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc"
- * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
- *
- *
- * @param str the String to abbreviate, may be null
- * @param middle the String to replace the middle characters with, may be null
- * @param length the length to abbreviate {@code str} to.
- * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
- * @since 2.5
- */
- public static String abbreviateMiddle(final String str, final String middle, final int length) {
- if (isEmpty(str) || isEmpty(middle)) {
- return str;
- }
-
- if (length >= str.length() || length < middle.length()+2) {
- return str;
- }
-
- final int targetSting = length-middle.length();
- final int startOffset = targetSting/2+targetSting%2;
- final int endOffset = str.length()-targetSting/2;
-
- return str.substring(0, startOffset) +
- middle +
- str.substring(endOffset);
- }
-
- // Difference
- //-----------------------------------------------------------------------
- /**
- * Compares two Strings, and returns the portion where they differ.
- * More precisely, return the remainder of the second String,
- * starting from where it's different from the first. This means that
- * the difference between "abc" and "ab" is the empty String and not "c".
- *
- * For example,
- * {@code difference("i am a machine", "i am a robot") -> "robot"}.
- *
- *
- * StringUtils.difference(null, null) = null
- * StringUtils.difference("", "") = ""
- * StringUtils.difference("", "abc") = "abc"
- * StringUtils.difference("abc", "") = ""
- * StringUtils.difference("abc", "abc") = ""
- * StringUtils.difference("abc", "ab") = ""
- * StringUtils.difference("ab", "abxyz") = "xyz"
- * StringUtils.difference("abcde", "abxyz") = "xyz"
- * StringUtils.difference("abcde", "xyz") = "xyz"
- *
- *
- * @param str1 the first String, may be null
- * @param str2 the second String, may be null
- * @return the portion of str2 where it differs from str1; returns the
- * empty String if they are equal
- * @see #indexOfDifference(CharSequence,CharSequence)
- * @since 2.0
- */
- public static String difference(final String str1, final String str2) {
- if (str1 == null) {
- return str2;
- }
- if (str2 == null) {
- return str1;
- }
- final int at = indexOfDifference(str1, str2);
- if (at == INDEX_NOT_FOUND) {
- return EMPTY;
- }
- return str2.substring(at);
- }
-
- /**
- * Compares two CharSequences, and returns the index at which the
- * CharSequences begin to differ.
- *
- * For example,
- * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}
- *
- *
- * StringUtils.indexOfDifference(null, null) = -1
- * StringUtils.indexOfDifference("", "") = -1
- * StringUtils.indexOfDifference("", "abc") = 0
- * StringUtils.indexOfDifference("abc", "") = 0
- * StringUtils.indexOfDifference("abc", "abc") = -1
- * StringUtils.indexOfDifference("ab", "abxyz") = 2
- * StringUtils.indexOfDifference("abcde", "abxyz") = 2
- * StringUtils.indexOfDifference("abcde", "xyz") = 0
- *
- *
- * @param cs1 the first CharSequence, may be null
- * @param cs2 the second CharSequence, may be null
- * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
- * @since 2.0
- * @since 3.0 Changed signature from indexOfDifference(String, String) to
- * indexOfDifference(CharSequence, CharSequence)
- */
- public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
- if (cs1 == cs2) {
- return INDEX_NOT_FOUND;
- }
- if (cs1 == null || cs2 == null) {
- return 0;
- }
- int i;
- for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
- if (cs1.charAt(i) != cs2.charAt(i)) {
- break;
- }
- }
- if (i < cs2.length() || i < cs1.length()) {
- return i;
- }
- return INDEX_NOT_FOUND;
- }
-
- /**
- * Compares all CharSequences in an array and returns the index at which the
- * CharSequences begin to differ.
- *
- * For example,
- * indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7
- *
- *
- * StringUtils.indexOfDifference(null) = -1
- * StringUtils.indexOfDifference(new String[] {}) = -1
- * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
- * StringUtils.indexOfDifference(new String[] {null, null}) = -1
- * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
- * StringUtils.indexOfDifference(new String[] {"", null}) = 0
- * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
- * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
- * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
- * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
- * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
- * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
- * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
- * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
- * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
- * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
- * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
- *
- *
- * @param css array of CharSequences, entries may be null
- * @return the index where the strings begin to differ; -1 if they are all equal
- * @since 2.4
- * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
- */
- public static int indexOfDifference(final CharSequence... css) {
- if (css == null || css.length <= 1) {
- return INDEX_NOT_FOUND;
- }
- boolean anyStringNull = false;
- boolean allStringsNull = true;
- final int arrayLen = css.length;
- int shortestStrLen = Integer.MAX_VALUE;
- int longestStrLen = 0;
-
- // find the min and max string lengths; this avoids checking to make
- // sure we are not exceeding the length of the string each time through
- // the bottom loop.
- for (final CharSequence cs : css) {
- if (cs == null) {
- anyStringNull = true;
- shortestStrLen = 0;
- } else {
- allStringsNull = false;
- shortestStrLen = Math.min(cs.length(), shortestStrLen);
- longestStrLen = Math.max(cs.length(), longestStrLen);
- }
- }
-
- // handle lists containing all nulls or all empty strings
- if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
- return INDEX_NOT_FOUND;
- }
-
- // handle lists containing some nulls or some empty strings
- if (shortestStrLen == 0) {
- return 0;
- }
-
- // find the position with the first difference across all strings
- int firstDiff = -1;
- for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
- final char comparisonChar = css[0].charAt(stringPos);
- for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
- if (css[arrayPos].charAt(stringPos) != comparisonChar) {
- firstDiff = stringPos;
- break;
- }
- }
- if (firstDiff != -1) {
- break;
- }
- }
-
- if (firstDiff == -1 && shortestStrLen != longestStrLen) {
- // we compared all of the characters up to the length of the
- // shortest string and didn't find a match, but the string lengths
- // vary, so return the length of the shortest string.
- return shortestStrLen;
- }
- return firstDiff;
- }
-
- /**
- * Compares all Strings in an array and returns the initial sequence of
- * characters that is common to all of them.
- *
- * For example,
- * getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "
- *
- *
- * StringUtils.getCommonPrefix(null) = ""
- * StringUtils.getCommonPrefix(new String[] {}) = ""
- * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
- * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
- * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
- * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
- * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
- * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
- * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
- * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
- * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
- * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
- * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
- * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
- * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
- * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
- * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
- *
- *
- * @param strs array of String objects, entries may be null
- * @return the initial sequence of characters that are common to all Strings
- * in the array; empty String if the array is null, the elements are all null
- * or if there is no common prefix.
- * @since 2.4
- */
- public static String getCommonPrefix(final String... strs) {
- if (strs == null || strs.length == 0) {
- return EMPTY;
- }
- final int smallestIndexOfDiff = indexOfDifference(strs);
- if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
- // all strings were identical
- if (strs[0] == null) {
- return EMPTY;
- }
- return strs[0];
- } else if (smallestIndexOfDiff == 0) {
- // there were no common initial characters
- return EMPTY;
- } else {
- // we found a common initial character sequence
- return strs[0].substring(0, smallestIndexOfDiff);
- }
- }
-
- // Misc
- //-----------------------------------------------------------------------
- /**
- * Find the Levenshtein distance between two Strings.
- *
- * This is the number of changes needed to change one String into
- * another, where each change is a single character modification (deletion,
- * insertion or substitution).
- *
- * The implementation uses a single-dimensional array of length s.length() + 1. See
- *
- * http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html for details.
- *
- *
- * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException
- * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException
- * StringUtils.getLevenshteinDistance("","") = 0
- * StringUtils.getLevenshteinDistance("","a") = 1
- * StringUtils.getLevenshteinDistance("aaapppp", "") = 7
- * StringUtils.getLevenshteinDistance("frog", "fog") = 1
- * StringUtils.getLevenshteinDistance("fly", "ant") = 3
- * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
- * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
- * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
- * StringUtils.getLevenshteinDistance("hello", "hallo") = 1
- *
- *
- * @param s the first String, must not be null
- * @param t the second String, must not be null
- * @return result distance
- * @throws IllegalArgumentException if either String input {@code null}
- * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
- * getLevenshteinDistance(CharSequence, CharSequence)
- * @deprecated as of 3.6, use commons-text
- *
- * LevenshteinDistance instead
- */
- @Deprecated
- public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
- if (s == null || t == null) {
- throw new IllegalArgumentException("Strings must not be null");
- }
-
- int n = s.length();
- int m = t.length();
-
- if (n == 0) {
- return m;
- } else if (m == 0) {
- return n;
- }
-
- if (n > m) {
- // swap the input strings to consume less memory
- final CharSequence tmp = s;
- s = t;
- t = tmp;
- n = m;
- m = t.length();
- }
-
- final int p[] = new int[n + 1];
- // indexes into strings s and t
- int i; // iterates through s
- int j; // iterates through t
- int upper_left;
- int upper;
-
- char t_j; // jth character of t
- int cost;
-
- for (i = 0; i <= n; i++) {
- p[i] = i;
- }
-
- for (j = 1; j <= m; j++) {
- upper_left = p[0];
- t_j = t.charAt(j - 1);
- p[0] = j;
-
- for (i = 1; i <= n; i++) {
- upper = p[i];
- cost = s.charAt(i - 1) == t_j ? 0 : 1;
- // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
- p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost);
- upper_left = upper;
- }
- }
-
- return p[n];
- }
-
- /**
- * Find the Levenshtein distance between two Strings if it's less than or equal to a given
- * threshold.
- *
- * This is the number of changes needed to change one String into
- * another, where each change is a single character modification (deletion,
- * insertion or substitution).
- *
- * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
- * and Chas Emerick's implementation of the Levenshtein distance algorithm from
- * http://www.merriampark.com/ld.htm
- *
- *
- * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException
- * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException
- * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException
- * StringUtils.getLevenshteinDistance("","", 0) = 0
- * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7
- * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7
- * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1
- * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
- * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
- * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
- * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
- *
- *
- * @param s the first String, must not be null
- * @param t the second String, must not be null
- * @param threshold the target threshold, must not be negative
- * @return result distance, or {@code -1} if the distance would be greater than the threshold
- * @throws IllegalArgumentException if either String input {@code null} or negative threshold
- * @deprecated as of 3.6, use commons-text
- *
- * LevenshteinDistance instead
- */
- @Deprecated
- public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
- if (s == null || t == null) {
- throw new IllegalArgumentException("Strings must not be null");
- }
- if (threshold < 0) {
- throw new IllegalArgumentException("Threshold must not be negative");
- }
-
- /*
- This implementation only computes the distance if it's less than or equal to the
- threshold value, returning -1 if it's greater. The advantage is performance: unbounded
- distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
- computing a diagonal stripe of width 2k + 1 of the cost table.
- It is also possible to use this to compute the unbounded Levenshtein distance by starting
- the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
- d is the distance.
-
- One subtlety comes from needing to ignore entries on the border of our stripe
- eg.
- p[] = |#|#|#|*
- d[] = *|#|#|#|
- We must ignore the entry to the left of the leftmost member
- We must ignore the entry above the rightmost member
-
- Another subtlety comes from our stripe running off the matrix if the strings aren't
- of the same size. Since string s is always swapped to be the shorter of the two,
- the stripe will always run off to the upper right instead of the lower left of the matrix.
-
- As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
- In this case we're going to walk a stripe of length 3. The matrix would look like so:
-
- 1 2 3 4 5
- 1 |#|#| | | |
- 2 |#|#|#| | |
- 3 | |#|#|#| |
- 4 | | |#|#|#|
- 5 | | | |#|#|
- 6 | | | | |#|
- 7 | | | | | |
-
- Note how the stripe leads off the table as there is no possible way to turn a string of length 5
- into one of length 7 in edit distance of 1.
-
- Additionally, this implementation decreases memory usage by using two
- single-dimensional arrays and swapping them back and forth instead of allocating
- an entire n by m matrix. This requires a few minor changes, such as immediately returning
- when it's detected that the stripe has run off the matrix and initially filling the arrays with
- large values so that entries we don't compute are ignored.
-
- See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
- */
-
- int n = s.length(); // length of s
- int m = t.length(); // length of t
-
- // if one string is empty, the edit distance is necessarily the length of the other
- if (n == 0) {
- return m <= threshold ? m : -1;
- } else if (m == 0) {
- return n <= threshold ? n : -1;
- } else if (Math.abs(n - m) > threshold) {
- // no need to calculate the distance if the length difference is greater than the threshold
- return -1;
- }
-
- if (n > m) {
- // swap the two strings to consume less memory
- final CharSequence tmp = s;
- s = t;
- t = tmp;
- n = m;
- m = t.length();
- }
-
- int p[] = new int[n + 1]; // 'previous' cost array, horizontally
- int d[] = new int[n + 1]; // cost array, horizontally
- int _d[]; // placeholder to assist in swapping p and d
-
- // fill in starting table values
- final int boundary = Math.min(n, threshold) + 1;
- for (int i = 0; i < boundary; i++) {
- p[i] = i;
- }
- // these fills ensure that the value above the rightmost entry of our
- // stripe will be ignored in following loop iterations
- Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
- Arrays.fill(d, Integer.MAX_VALUE);
-
- // iterates through t
- for (int j = 1; j <= m; j++) {
- final char t_j = t.charAt(j - 1); // jth character of t
- d[0] = j;
-
- // compute stripe indices, constrain to array size
- final int min = Math.max(1, j - threshold);
- final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
-
- // the stripe may lead off of the table if s and t are of different sizes
- if (min > max) {
- return -1;
- }
-
- // ignore entry left of leftmost
- if (min > 1) {
- d[min - 1] = Integer.MAX_VALUE;
- }
-
- // iterates through [min, max] in s
- for (int i = min; i <= max; i++) {
- if (s.charAt(i - 1) == t_j) {
- // diagonally left and up
- d[i] = p[i - 1];
- } else {
- // 1 + minimum of cell to the left, to the top, diagonally left and up
- d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
- }
- }
-
- // copy current distance counts to 'previous row' distance counts
- _d = p;
- p = d;
- d = _d;
- }
-
- // if p[n] is greater than the threshold, there's no guarantee on it being the correct
- // distance
- if (p[n] <= threshold) {
- return p[n];
- }
- return -1;
- }
-
- /**
- * Find the Jaro Winkler Distance which indicates the similarity score between two Strings.
- *
- * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
- * Winkler increased this measure for matching initial characters.
- *
- * This implementation is based on the Jaro Winkler similarity algorithm
- * from http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance .
- *
- *
- * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException
- * StringUtils.getJaroWinklerDistance("","") = 0.0
- * StringUtils.getJaroWinklerDistance("","a") = 0.0
- * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0
- * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93
- * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0
- * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
- * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
- * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
- * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88
- * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
- * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95
- * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
- * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
- *
- *
- * @param first the first String, must not be null
- * @param second the second String, must not be null
- * @return result distance
- * @throws IllegalArgumentException if either String input {@code null}
- * @since 3.3
- * @deprecated as of 3.6, use commons-text
- *
- * JaroWinklerDistance instead
- */
- @Deprecated
- public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
- final double DEFAULT_SCALING_FACTOR = 0.1;
-
- if (first == null || second == null) {
- throw new IllegalArgumentException("Strings must not be null");
- }
-
- final int[] mtp = matches(first, second);
- final double m = mtp[0];
- if (m == 0) {
- return 0D;
- }
- final double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3;
- final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
- return Math.round(jw * 100.0D) / 100.0D;
- }
-
- private static int[] matches(final CharSequence first, final CharSequence second) {
- CharSequence max, min;
- if (first.length() > second.length()) {
- max = first;
- min = second;
- } else {
- max = second;
- min = first;
- }
- final int range = Math.max(max.length() / 2 - 1, 0);
- final int[] matchIndexes = new int[min.length()];
- Arrays.fill(matchIndexes, -1);
- final boolean[] matchFlags = new boolean[max.length()];
- int matches = 0;
- for (int mi = 0; mi < min.length(); mi++) {
- final char c1 = min.charAt(mi);
- for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
- if (!matchFlags[xi] && c1 == max.charAt(xi)) {
- matchIndexes[mi] = xi;
- matchFlags[xi] = true;
- matches++;
- break;
- }
- }
- }
- final char[] ms1 = new char[matches];
- final char[] ms2 = new char[matches];
- for (int i = 0, si = 0; i < min.length(); i++) {
- if (matchIndexes[i] != -1) {
- ms1[si] = min.charAt(i);
- si++;
- }
- }
- for (int i = 0, si = 0; i < max.length(); i++) {
- if (matchFlags[i]) {
- ms2[si] = max.charAt(i);
- si++;
- }
- }
- int transpositions = 0;
- for (int mi = 0; mi < ms1.length; mi++) {
- if (ms1[mi] != ms2[mi]) {
- transpositions++;
- }
- }
- int prefix = 0;
- for (int mi = 0; mi < min.length(); mi++) {
- if (first.charAt(mi) == second.charAt(mi)) {
- prefix++;
- } else {
- break;
- }
- }
- return new int[] { matches, transpositions / 2, prefix, max.length() };
- }
-
- /**
- * Find the Fuzzy Distance which indicates the similarity score between two Strings.
- *
- * This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
- * TextMate, Atom and others. One point is given for every matched character. Subsequent
- * matches yield two bonus points. A higher score indicates a higher similarity.
- *
- *
- * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException
- * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0
- * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0
- * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1
- * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1
- * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2
- * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4
- * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
- *
- *
- * @param term a full term that should be matched against, must not be null
- * @param query the query that will be matched against a term, must not be null
- * @param locale This string matching logic is case insensitive. A locale is necessary to normalize
- * both Strings to lower case.
- * @return result score
- * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
- * @since 3.4
- * @deprecated as of 3.6, use commons-text
- *
- * FuzzyScore instead
- */
- @Deprecated
- public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
- if (term == null || query == null) {
- throw new IllegalArgumentException("Strings must not be null");
- } else if (locale == null) {
- throw new IllegalArgumentException("Locale must not be null");
- }
-
- // fuzzy logic is case insensitive. We normalize the Strings to lower
- // case right from the start. Turning characters to lower case
- // via Character.toLowerCase(char) is unfortunately insufficient
- // as it does not accept a locale.
- final String termLowerCase = term.toString().toLowerCase(locale);
- final String queryLowerCase = query.toString().toLowerCase(locale);
-
- // the resulting score
- int score = 0;
-
- // the position in the term which will be scanned next for potential
- // query character matches
- int termIndex = 0;
-
- // index of the previously matched character in the term
- int previousMatchingCharacterIndex = Integer.MIN_VALUE;
-
- for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
- final char queryChar = queryLowerCase.charAt(queryIndex);
-
- boolean termCharacterMatchFound = false;
- for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
- final char termChar = termLowerCase.charAt(termIndex);
-
- if (queryChar == termChar) {
- // simple character matches result in one point
- score++;
-
- // subsequent character matches further improve
- // the score.
- if (previousMatchingCharacterIndex + 1 == termIndex) {
- score += 2;
- }
-
- previousMatchingCharacterIndex = termIndex;
-
- // we can leave the nested loop. Every character in the
- // query can match at most one character in the term.
- termCharacterMatchFound = true;
- }
- }
- }
-
- return score;
- }
-
- // startsWith
- //-----------------------------------------------------------------------
-
- /**
- * Check if a CharSequence starts with a specified prefix.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case sensitive.
- *
- *
- * StringUtils.startsWith(null, null) = true
- * StringUtils.startsWith(null, "abc") = false
- * StringUtils.startsWith("abcdef", null) = false
- * StringUtils.startsWith("abcdef", "abc") = true
- * StringUtils.startsWith("ABCDEF", "abc") = false
- *
- *
- * @see String#startsWith(String)
- * @param str the CharSequence to check, may be null
- * @param prefix the prefix to find, may be null
- * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
- * both {@code null}
- * @since 2.4
- * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
- */
- public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
- return startsWith(str, prefix, false);
- }
-
- /**
- * Case insensitive check if a CharSequence starts with a specified prefix.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case insensitive.
- *
- *
- * StringUtils.startsWithIgnoreCase(null, null) = true
- * StringUtils.startsWithIgnoreCase(null, "abc") = false
- * StringUtils.startsWithIgnoreCase("abcdef", null) = false
- * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
- * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
- *
- *
- * @see String#startsWith(String)
- * @param str the CharSequence to check, may be null
- * @param prefix the prefix to find, may be null
- * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
- * both {@code null}
- * @since 2.4
- * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
- */
- public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
- return startsWith(str, prefix, true);
- }
-
- /**
- * Check if a CharSequence starts with a specified prefix (optionally case insensitive).
- *
- * @see String#startsWith(String)
- * @param str the CharSequence to check, may be null
- * @param prefix the prefix to find, may be null
- * @param ignoreCase indicates whether the compare should ignore case
- * (case insensitive) or not.
- * @return {@code true} if the CharSequence starts with the prefix or
- * both {@code null}
- */
- private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
- if (str == null || prefix == null) {
- return str == prefix;
- }
- if (prefix.length() > str.length()) {
- return false;
- }
- return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
- }
-
- /**
- * Check if a CharSequence starts with any of the provided case-sensitive prefixes.
- *
- *
- * StringUtils.startsWithAny(null, null) = false
- * StringUtils.startsWithAny(null, new String[] {"abc"}) = false
- * StringUtils.startsWithAny("abcxyz", null) = false
- * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
- * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
- * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
- * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
- * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
- *
- *
- * @param sequence the CharSequence to check, may be null
- * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
- * @see StringUtils#startsWith(CharSequence, CharSequence)
- * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
- * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
- * @since 2.5
- * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
- */
- public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
- if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
- return false;
- }
- for (final CharSequence searchString : searchStrings) {
- if (startsWith(sequence, searchString)) {
- return true;
- }
- }
- return false;
- }
-
- // endsWith
- //-----------------------------------------------------------------------
-
- /**
- * Check if a CharSequence ends with a specified suffix.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case sensitive.
- *
- *
- * StringUtils.endsWith(null, null) = true
- * StringUtils.endsWith(null, "def") = false
- * StringUtils.endsWith("abcdef", null) = false
- * StringUtils.endsWith("abcdef", "def") = true
- * StringUtils.endsWith("ABCDEF", "def") = false
- * StringUtils.endsWith("ABCDEF", "cde") = false
- * StringUtils.endsWith("ABCDEF", "") = true
- *
- *
- * @see String#endsWith(String)
- * @param str the CharSequence to check, may be null
- * @param suffix the suffix to find, may be null
- * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or
- * both {@code null}
- * @since 2.4
- * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
- */
- public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
- return endsWith(str, suffix, false);
- }
-
- /**
- * Case insensitive check if a CharSequence ends with a specified suffix.
- *
- * {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case insensitive.
- *
- *
- * StringUtils.endsWithIgnoreCase(null, null) = true
- * StringUtils.endsWithIgnoreCase(null, "def") = false
- * StringUtils.endsWithIgnoreCase("abcdef", null) = false
- * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
- * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
- * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
- *
- *
- * @see String#endsWith(String)
- * @param str the CharSequence to check, may be null
- * @param suffix the suffix to find, may be null
- * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or
- * both {@code null}
- * @since 2.4
- * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
- */
- public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
- return endsWith(str, suffix, true);
- }
-
- /**
- * Check if a CharSequence ends with a specified suffix (optionally case insensitive).
- *
- * @see String#endsWith(String)
- * @param str the CharSequence to check, may be null
- * @param suffix the suffix to find, may be null
- * @param ignoreCase indicates whether the compare should ignore case
- * (case insensitive) or not.
- * @return {@code true} if the CharSequence starts with the prefix or
- * both {@code null}
- */
- private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
- if (str == null || suffix == null) {
- return str == suffix;
- }
- if (suffix.length() > str.length()) {
- return false;
- }
- final int strOffset = str.length() - suffix.length();
- return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length());
- }
-
- /**
- *
- * Similar to http://www.w3.org/TR/xpath/#function-normalize
- * -space
- *
- *
- * The function returns the argument string with whitespace normalized by using
- * {@link #trim(String)} to remove leading and trailing whitespace
- * and then replacing sequences of whitespace characters by a single space.
- *
- * In XML Whitespace characters are the same as those allowed by the S production, which is S ::= (#x20 | #x9 | #xD | #xA)+
- *
- * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
- *
- *
For reference:
- *
- * \x0B = vertical tab
- * \f = #xC = form feed
- * #x20 = space
- * #x9 = \t
- * #xA = \n
- * #xD = \r
- *
- *
- *
- * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
- * normalize. Additionally {@link #trim(String)} removes control characters (char <= 32) from both
- * ends of this String.
- *
- *
- * @see Pattern
- * @see #trim(String)
- * @see http://www.w3.org/TR/xpath/#function-normalize-space
- * @param str the source String to normalize whitespaces from, may be null
- * @return the modified string with whitespace normalized, {@code null} if null String input
- *
- * @since 3.0
- */
- public static String normalizeSpace(final String str) {
- // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
- // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
- if (isEmpty(str)) {
- return str;
- }
- final int size = str.length();
- final char[] newChars = new char[size];
- int count = 0;
- int whitespacesCount = 0;
- boolean startWhitespaces = true;
- for (int i = 0; i < size; i++) {
- final char actualChar = str.charAt(i);
- final boolean isWhitespace = Character.isWhitespace(actualChar);
- if (isWhitespace) {
- if (whitespacesCount == 0 && !startWhitespaces) {
- newChars[count++] = SPACE.charAt(0);
- }
- whitespacesCount++;
- } else {
- startWhitespaces = false;
- newChars[count++] = (actualChar == 160 ? 32 : actualChar);
- whitespacesCount = 0;
- }
- }
- if (startWhitespaces) {
- return EMPTY;
- }
- return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
- }
-
- /**
- * Check if a CharSequence ends with any of the provided case-sensitive suffixes.
- *
- *
- * StringUtils.endsWithAny(null, null) = false
- * StringUtils.endsWithAny(null, new String[] {"abc"}) = false
- * StringUtils.endsWithAny("abcxyz", null) = false
- * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
- * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
- * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
- * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
- * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
- *
- *
- * @param sequence the CharSequence to check, may be null
- * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
- * @see StringUtils#endsWith(CharSequence, CharSequence)
- * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
- * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
- * @since 3.0
- */
- public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
- if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
- return false;
- }
- for (final CharSequence searchString : searchStrings) {
- if (endsWith(sequence, searchString)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Appends the suffix to the end of the string if the string does not
- * already end with the suffix.
- *
- * @param str The string.
- * @param suffix The suffix to append to the end of the string.
- * @param ignoreCase Indicates whether the compare should ignore case.
- * @param suffixes Additional suffixes that are valid terminators (optional).
- *
- * @return A new String if suffix was appended, the same string otherwise.
- */
- private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
- if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) {
- return str;
- }
- if (suffixes != null && suffixes.length > 0) {
- for (final CharSequence s : suffixes) {
- if (endsWith(str, s, ignoreCase)) {
- return str;
- }
- }
- }
- return str + suffix.toString();
- }
-
- /**
- * Appends the suffix to the end of the string if the string does not
- * already end with any of the suffixes.
- *
- *
- * StringUtils.appendIfMissing(null, null) = null
- * StringUtils.appendIfMissing("abc", null) = "abc"
- * StringUtils.appendIfMissing("", "xyz") = "xyz"
- * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz"
- * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
- * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
- *
- * With additional suffixes,
- *
- * StringUtils.appendIfMissing(null, null, null) = null
- * StringUtils.appendIfMissing("abc", null, null) = "abc"
- * StringUtils.appendIfMissing("", "xyz", null) = "xyz"
- * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
- * StringUtils.appendIfMissing("abc", "xyz", "") = "abc"
- * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz"
- * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
- * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
- * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
- * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
- *
- *
- * @param str The string.
- * @param suffix The suffix to append to the end of the string.
- * @param suffixes Additional suffixes that are valid terminators.
- *
- * @return A new String if suffix was appended, the same string otherwise.
- *
- * @since 3.2
- */
- public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
- return appendIfMissing(str, suffix, false, suffixes);
- }
-
- /**
- * Appends the suffix to the end of the string if the string does not
- * already end, case insensitive, with any of the suffixes.
- *
- *
- * StringUtils.appendIfMissingIgnoreCase(null, null) = null
- * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc"
- * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz"
- * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz"
- * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
- * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
- *
- * With additional suffixes,
- *
- * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null
- * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc"
- * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz"
- * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
- * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc"
- * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "axyz"
- * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
- * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
- * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
- * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
- *
- *
- * @param str The string.
- * @param suffix The suffix to append to the end of the string.
- * @param suffixes Additional suffixes that are valid terminators.
- *
- * @return A new String if suffix was appended, the same string otherwise.
- *
- * @since 3.2
- */
- public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
- return appendIfMissing(str, suffix, true, suffixes);
- }
-
- /**
- * Prepends the prefix to the start of the string if the string does not
- * already start with any of the prefixes.
- *
- * @param str The string.
- * @param prefix The prefix to prepend to the start of the string.
- * @param ignoreCase Indicates whether the compare should ignore case.
- * @param prefixes Additional prefixes that are valid (optional).
- *
- * @return A new String if prefix was prepended, the same string otherwise.
- */
- private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
- if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) {
- return str;
- }
- if (prefixes != null && prefixes.length > 0) {
- for (final CharSequence p : prefixes) {
- if (startsWith(str, p, ignoreCase)) {
- return str;
- }
- }
- }
- return prefix.toString() + str;
- }
-
- /**
- * Prepends the prefix to the start of the string if the string does not
- * already start with any of the prefixes.
- *
- *
- * StringUtils.prependIfMissing(null, null) = null
- * StringUtils.prependIfMissing("abc", null) = "abc"
- * StringUtils.prependIfMissing("", "xyz") = "xyz"
- * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
- * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
- * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
- *
- * With additional prefixes,
- *
- * StringUtils.prependIfMissing(null, null, null) = null
- * StringUtils.prependIfMissing("abc", null, null) = "abc"
- * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
- * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
- * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
- * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
- * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
- * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
- * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
- * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
- *
- *
- * @param str The string.
- * @param prefix The prefix to prepend to the start of the string.
- * @param prefixes Additional prefixes that are valid.
- *
- * @return A new String if prefix was prepended, the same string otherwise.
- *
- * @since 3.2
- */
- public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
- return prependIfMissing(str, prefix, false, prefixes);
- }
-
- /**
- * Prepends the prefix to the start of the string if the string does not
- * already start, case insensitive, with any of the prefixes.
- *
- *
- * StringUtils.prependIfMissingIgnoreCase(null, null) = null
- * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
- * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
- * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
- * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
- * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
- *
- * With additional prefixes,
- *
- * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
- * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
- * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
- * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
- * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
- * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
- * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
- * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
- * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
- * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
- *
- *
- * @param str The string.
- * @param prefix The prefix to prepend to the start of the string.
- * @param prefixes Additional prefixes that are valid (optional).
- *
- * @return A new String if prefix was prepended, the same string otherwise.
- *
- * @since 3.2
- */
- public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
- return prependIfMissing(str, prefix, true, prefixes);
- }
-
- /**
- * Converts a byte[] to a String using the specified character encoding.
- *
- * @param bytes
- * the byte array to read from
- * @param charsetName
- * the encoding to use, if null then use the platform default
- * @return a new String
- * @throws UnsupportedEncodingException
- * If the named charset is not supported
- * @throws NullPointerException
- * if the input is null
- * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
- * @since 3.1
- */
- @Deprecated
- public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException {
- return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset());
- }
-
- /**
- * Converts a byte[] to a String using the specified character encoding.
- *
- * @param bytes
- * the byte array to read from
- * @param charset
- * the encoding to use, if null then use the platform default
- * @return a new String
- * @throws NullPointerException
- * if {@code bytes} is null
- * @since 3.2
- * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
- */
- public static String toEncodedString(final byte[] bytes, final Charset charset) {
- return new String(bytes, charset != null ? charset : Charset.defaultCharset());
- }
-
- /**
- *
- * Wraps a string with a char.
- *
- *
- *
- * StringUtils.wrap(null, *) = null
- * StringUtils.wrap("", *) = ""
- * StringUtils.wrap("ab", '\0') = "ab"
- * StringUtils.wrap("ab", 'x') = "xabx"
- * StringUtils.wrap("ab", '\'') = "'ab'"
- * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
- *
- *
- * @param str
- * the string to be wrapped, may be {@code null}
- * @param wrapWith
- * the char that will wrap {@code str}
- * @return the wrapped string, or {@code null} if {@code str==null}
- * @since 3.4
- */
- public static String wrap(final String str, final char wrapWith) {
-
- if (isEmpty(str) || wrapWith == CharUtils.NUL) {
- return str;
- }
-
- return wrapWith + str + wrapWith;
- }
-
- /**
- *
- * Wraps a String with another String.
- *
- *
- *
- * A {@code null} input String returns {@code null}.
- *
- *
- *
- * StringUtils.wrap(null, *) = null
- * StringUtils.wrap("", *) = ""
- * StringUtils.wrap("ab", null) = "ab"
- * StringUtils.wrap("ab", "x") = "xabx"
- * StringUtils.wrap("ab", "\"") = "\"ab\""
- * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\""
- * StringUtils.wrap("ab", "'") = "'ab'"
- * StringUtils.wrap("'abcd'", "'") = "''abcd''"
- * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
- * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\""
- *
- *
- * @param str
- * the String to be wrapper, may be null
- * @param wrapWith
- * the String that will wrap str
- * @return wrapped String, {@code null} if null String input
- * @since 3.4
- */
- public static String wrap(final String str, final String wrapWith) {
-
- if (isEmpty(str) || isEmpty(wrapWith)) {
- return str;
- }
-
- return wrapWith.concat(str).concat(wrapWith);
- }
-
- /**
- *
- * Wraps a string with a char if that char is missing from the start or end of the given string.
- *
- *
- *
- * StringUtils.wrap(null, *) = null
- * StringUtils.wrap("", *) = ""
- * StringUtils.wrap("ab", '\0') = "ab"
- * StringUtils.wrap("ab", 'x') = "xabx"
- * StringUtils.wrap("ab", '\'') = "'ab'"
- * StringUtils.wrap("\"ab\"", '\"') = "\"ab\""
- * StringUtils.wrap("/", '/') = "/"
- * StringUtils.wrap("a/b/c", '/') = "/a/b/c/"
- * StringUtils.wrap("/a/b/c", '/') = "/a/b/c/"
- * StringUtils.wrap("a/b/c/", '/') = "/a/b/c/"
- *
- *
- * @param str
- * the string to be wrapped, may be {@code null}
- * @param wrapWith
- * the char that will wrap {@code str}
- * @return the wrapped string, or {@code null} if {@code str==null}
- * @since 3.5
- */
- public static String wrapIfMissing(final String str, final char wrapWith) {
- if (isEmpty(str) || wrapWith == CharUtils.NUL) {
- return str;
- }
- final StringBuilder builder = new StringBuilder(str.length() + 2);
- if (str.charAt(0) != wrapWith) {
- builder.append(wrapWith);
- }
- builder.append(str);
- if (str.charAt(str.length() - 1) != wrapWith) {
- builder.append(wrapWith);
- }
- return builder.toString();
- }
-
- /**
- *
- * Wraps a string with a string if that string is missing from the start or end of the given string.
- *
- *
- *
- * StringUtils.wrap(null, *) = null
- * StringUtils.wrap("", *) = ""
- * StringUtils.wrap("ab", null) = "ab"
- * StringUtils.wrap("ab", "x") = "xabx"
- * StringUtils.wrap("ab", "\"") = "\"ab\""
- * StringUtils.wrap("\"ab\"", "\"") = "\"ab\""
- * StringUtils.wrap("ab", "'") = "'ab'"
- * StringUtils.wrap("'abcd'", "'") = "'abcd'"
- * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
- * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\""
- * StringUtils.wrap("/", "/") = "/"
- * StringUtils.wrap("a/b/c", "/") = "/a/b/c/"
- * StringUtils.wrap("/a/b/c", "/") = "/a/b/c/"
- * StringUtils.wrap("a/b/c/", "/") = "/a/b/c/"
- *
- *
- * @param str
- * the string to be wrapped, may be {@code null}
- * @param wrapWith
- * the char that will wrap {@code str}
- * @return the wrapped string, or {@code null} if {@code str==null}
- * @since 3.5
- */
- public static String wrapIfMissing(final String str, final String wrapWith) {
- if (isEmpty(str) || isEmpty(wrapWith)) {
- return str;
- }
- final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
- if (!str.startsWith(wrapWith)) {
- builder.append(wrapWith);
- }
- builder.append(str);
- if (!str.endsWith(wrapWith)) {
- builder.append(wrapWith);
- }
- return builder.toString();
- }
-
- /**
- *
- * Unwraps a given string from anther string.
- *
- *
- *
- * StringUtils.unwrap(null, null) = null
- * StringUtils.unwrap(null, "") = null
- * StringUtils.unwrap(null, "1") = null
- * StringUtils.unwrap("\'abc\'", "\'") = "abc"
- * StringUtils.unwrap("\"abc\"", "\"") = "abc"
- * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB"
- * StringUtils.unwrap("A", "#") = "A"
- * StringUtils.unwrap("#A", "#") = "#A"
- * StringUtils.unwrap("A#", "#") = "A#"
- *
- *
- * @param str
- * the String to be unwrapped, can be null
- * @param wrapToken
- * the String used to unwrap
- * @return unwrapped String or the original string
- * if it is not quoted properly with the wrapToken
- * @since 3.6
- */
- public static String unwrap(final String str, final String wrapToken) {
- if (isEmpty(str) || isEmpty(wrapToken)) {
- return str;
- }
-
- if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) {
- final int startIndex = str.indexOf(wrapToken);
- final int endIndex = str.lastIndexOf(wrapToken);
- final int wrapLength = wrapToken.length();
- if (startIndex != -1 && endIndex != -1) {
- return str.substring(startIndex + wrapLength, endIndex);
- }
- }
-
- return str;
- }
-
- /**
- *
- * Unwraps a given string from a character.
- *
- *
- *
- * StringUtils.unwrap(null, null) = null
- * StringUtils.unwrap(null, '\0') = null
- * StringUtils.unwrap(null, '1') = null
- * StringUtils.unwrap("\'abc\'", '\'') = "abc"
- * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA"
- * StringUtils.unwrap("A", '#') = "A"
- * StringUtils.unwrap("#A", '#') = "#A"
- * StringUtils.unwrap("A#", '#') = "A#"
- *
- *
- * @param str
- * the String to be unwrapped, can be null
- * @param wrapChar
- * the character used to unwrap
- * @return unwrapped String or the original string
- * if it is not quoted properly with the wrapChar
- * @since 3.6
- */
- public static String unwrap(final String str, final char wrapChar) {
- if (isEmpty(str) || wrapChar == CharUtils.NUL) {
- return str;
- }
-
- if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
- final int startIndex = 0;
- final int endIndex = str.length() - 1;
- if (endIndex != -1) {
- return str.substring(startIndex + 1, endIndex);
- }
- }
-
- return str;
- }
-
- /**
- * Converts a {@code CharSequence} into an array of code points.
- *
- * Valid pairs of surrogate code units will be converted into a single supplementary
- * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or
- * a low surrogate not preceded by a high surrogate) will be returned as-is.
- *
- *
- * StringUtils.toCodePoints(null) = null
- * StringUtils.toCodePoints("") = [] // empty array
- *
- *
- * @param str the character sequence to convert
- * @return an array of code points
- * @since 3.6
- */
- public static int[] toCodePoints(final CharSequence str) {
- if (str == null) {
- return null;
- }
- if (str.length() == 0) {
- return ArrayUtils.EMPTY_INT_ARRAY;
- }
-
- final String s = str.toString();
- final int[] result = new int[s.codePointCount(0, s.length())];
- int index = 0;
- for (int i = 0; i < result.length; i++) {
- result[i] = s.codePointAt(index);
- index += Character.charCount(result[i]);
- }
- return result;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringBuilder.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringBuilder.java
deleted file mode 100644
index a1cd2225..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringBuilder.java
+++ /dev/null
@@ -1,1009 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-
-public class ToStringBuilder implements Builder {
-
- /**
- * The default style of output to use, not null.
- */
- private static volatile ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
-
- //----------------------------------------------------------------------------
-
- /**
- * Gets the default ToStringStyle to use.
- *
- * This method gets a singleton default value, typically for the whole JVM.
- * Changing this default should generally only be done during application startup.
- * It is recommended to pass a ToStringStyle to the constructor instead
- * of using this global default.
- *
- * This method can be used from multiple threads.
- * Internally, a volatile variable is used to provide the guarantee
- * that the latest value set using {@link #setDefaultStyle} is the value returned.
- * It is strongly recommended that the default style is only changed during application startup.
- *
- * One reason for changing the default could be to have a verbose style during
- * development and a compact style in production.
- *
- * @return the default ToStringStyle, never null
- */
- public static ToStringStyle getDefaultStyle() {
- return defaultStyle;
- }
-
- /**
- * Sets the default ToStringStyle to use.
- *
- * This method sets a singleton default value, typically for the whole JVM.
- * Changing this default should generally only be done during application startup.
- * It is recommended to pass a ToStringStyle to the constructor instead
- * of changing this global default.
- *
- * This method is not intended for use from multiple threads.
- * Internally, a volatile variable is used to provide the guarantee
- * that the latest value set is the value returned from {@link #getDefaultStyle}.
- *
- * @param style the default ToStringStyle
- * @throws IllegalArgumentException if the style is null
- */
- public static void setDefaultStyle(final ToStringStyle style) {
- Validate.isTrue(style != null, "The style must not be null");
- defaultStyle = style;
- }
-
- //----------------------------------------------------------------------------
- /**
- * Uses ReflectionToStringBuilder to generate a
- * toString for the specified object.
- *
- * @param object the Object to be output
- * @return the String result
- * @see ReflectionToStringBuilder#toString(Object)
- */
- public static String reflectionToString(final Object object) {
- return ReflectionToStringBuilder.toString(object);
- }
-
- /**
- * Uses ReflectionToStringBuilder to generate a
- * toString for the specified object.
- *
- * @param object the Object to be output
- * @param style the style of the toString to create, may be null
- * @return the String result
- * @see ReflectionToStringBuilder#toString(Object, ToStringStyle)
- */
- public static String reflectionToString(final Object object, final ToStringStyle style) {
- return ReflectionToStringBuilder.toString(object, style);
- }
-
- /**
- * Uses ReflectionToStringBuilder to generate a
- * toString for the specified object.
- *
- * @param object the Object to be output
- * @param style the style of the toString to create, may be null
- * @param outputTransients whether to include transient fields
- * @return the String result
- * @see ReflectionToStringBuilder#toString(Object, ToStringStyle,boolean)
- */
- public static String reflectionToString(final Object object, final ToStringStyle style, final boolean outputTransients) {
- return ReflectionToStringBuilder.toString(object, style, outputTransients, false, null);
- }
-
- /**
- * Uses ReflectionToStringBuilder to generate a
- * toString for the specified object.
- *
- * @param the type of the object
- * @param object the Object to be output
- * @param style the style of the toString to create, may be null
- * @param outputTransients whether to include transient fields
- * @param reflectUpToClass the superclass to reflect up to (inclusive), may be null
- * @return the String result
- * @see ReflectionToStringBuilder#toString(Object, ToStringStyle,boolean,boolean,Class)
- * @since 2.0
- */
- public static String reflectionToString(
- final T object,
- final ToStringStyle style,
- final boolean outputTransients,
- final Class super T> reflectUpToClass) {
- return ReflectionToStringBuilder.toString(object, style, outputTransients, false, reflectUpToClass);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Current toString buffer, not null.
- */
- private final StringBuffer buffer;
- /**
- * The object being output, may be null.
- */
- private final Object object;
- /**
- * The style of output to use, not null.
- */
- private final ToStringStyle style;
-
- /**
- * Constructs a builder for the specified object using the default output style.
- *
- * This default style is obtained from {@link #getDefaultStyle()}.
- *
- * @param object the Object to build a toString for, not recommended to be null
- */
- public ToStringBuilder(final Object object) {
- this(object, null, null);
- }
-
- /**
- * Constructs a builder for the specified object using the defined output style.
- *
- * If the style is null, the default style is used.
- *
- * @param object the Object to build a toString for, not recommended to be null
- * @param style the style of the toString to create, null uses the default style
- */
- public ToStringBuilder(final Object object, final ToStringStyle style) {
- this(object, style, null);
- }
-
- /**
- * Constructs a builder for the specified object.
- *
- * If the style is null, the default style is used.
- *
- * If the buffer is null, a new one is created.
- *
- * @param object the Object to build a toString for, not recommended to be null
- * @param style the style of the toString to create, null uses the default style
- * @param buffer the StringBuffer to populate, may be null
- */
- public ToStringBuilder(final Object object, ToStringStyle style, StringBuffer buffer) {
- if (style == null) {
- style = getDefaultStyle();
- }
- if (buffer == null) {
- buffer = new StringBuffer(512);
- }
- this.buffer = buffer;
- this.style = style;
- this.object = object;
-
- style.appendStart(buffer, object);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a boolean
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final boolean value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a boolean
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final boolean[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a byte
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final byte value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a byte
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final byte[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a char
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final char value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a char
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final char[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a double
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final double value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a double
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final double[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a float
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final float value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a float
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final float[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an int
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final int value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an int
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final int[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a long
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final long value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a long
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final long[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an Object
- * value.
- *
- * @param obj the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final Object obj) {
- style.append(buffer, null, obj, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an Object
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final Object[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a short
- * value.
- *
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final short value) {
- style.append(buffer, null, value);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a short
- * array.
- *
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final short[] array) {
- style.append(buffer, null, array, null);
- return this;
- }
-
- /**
- * Append to the toString a boolean
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final boolean value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a boolean
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the hashCode
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final boolean[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a boolean
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final boolean[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an byte
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final byte value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a byte array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final byte[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a byte
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final byte[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- *
Append to the toString a char
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final char value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a char
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final char[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a char
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final char[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString a double
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final double value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a double
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final double[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a double
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final double[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an float
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final float value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a float
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final float[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a float
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final float[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an int
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final int value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString an int
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final int[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString an int
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final int[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString a long
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final long value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a long
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final long[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a long
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final long[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an Object
- * value.
- *
- * @param fieldName the field name
- * @param obj the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final Object obj) {
- style.append(buffer, fieldName, obj, null);
- return this;
- }
-
- /**
- * Append to the toString an Object
- * value.
- *
- * @param fieldName the field name
- * @param obj the value to add to the toString
- * @param fullDetail true for detail,
- * false for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final Object obj, final boolean fullDetail) {
- style.append(buffer, fieldName, obj, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an Object
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final Object[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString an Object
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final Object[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- * Append to the toString an short
- * value.
- *
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final short value) {
- style.append(buffer, fieldName, value);
- return this;
- }
-
- /**
- * Append to the toString a short
- * array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final short[] array) {
- style.append(buffer, fieldName, array, null);
- return this;
- }
-
- /**
- * Append to the toString a short
- * array.
- *
- * A boolean parameter controls the level of detail to show.
- * Setting true will output the array in full. Setting
- * false will output a summary, typically the size of
- * the array.
- *
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info
- * @return this
- */
- public ToStringBuilder append(final String fieldName, final short[] array, final boolean fullDetail) {
- style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
- return this;
- }
-
- /**
- *
Appends with the same format as the default Object toString()
- * method. Appends the class name followed by
- * {@link System#identityHashCode(Object)}.
- *
- * @param srcObject the Object whose class name and id to output
- * @return this
- * @since 2.0
- */
- public ToStringBuilder appendAsObjectToString(final Object srcObject) {
- ObjectUtils.identityToString(this.getStringBuffer(), srcObject);
- return this;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append the toString from the superclass.
- *
- * This method assumes that the superclass uses the same ToStringStyle
- * as this one.
- *
- * If superToString is null, no change is made.
- *
- * @param superToString the result of super.toString()
- * @return this
- * @since 2.0
- */
- public ToStringBuilder appendSuper(final String superToString) {
- if (superToString != null) {
- style.appendSuper(buffer, superToString);
- }
- return this;
- }
-
- /**
- * Append the toString from another object.
- *
- * This method is useful where a class delegates most of the implementation of
- * its properties to another class. You can then call toString() on
- * the other class and pass the result into this method.
- *
- *
- * private AnotherObject delegate;
- * private String fieldInThisClass;
- *
- * public String toString() {
- * return new ToStringBuilder(this).
- * appendToString(delegate.toString()).
- * append(fieldInThisClass).
- * toString();
- * }
- *
- * This method assumes that the other object uses the same ToStringStyle
- * as this one.
- *
- * If the toString is null, no change is made.
- *
- * @param toString the result of toString() on another object
- * @return this
- * @since 2.0
- */
- public ToStringBuilder appendToString(final String toString) {
- if (toString != null) {
- style.appendToString(buffer, toString);
- }
- return this;
- }
-
- /**
- * Returns the Object being output.
- *
- * @return The object being output.
- * @since 2.0
- */
- public Object getObject() {
- return object;
- }
-
- /**
- * Gets the StringBuffer being populated.
- *
- * @return the StringBuffer being populated
- */
- public StringBuffer getStringBuffer() {
- return buffer;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Gets the ToStringStyle being used.
- *
- * @return the ToStringStyle being used
- * @since 2.0
- */
- public ToStringStyle getStyle() {
- return style;
- }
-
- /**
- * Returns the built toString.
- *
- * This method appends the end of data indicator, and can only be called once.
- * Use {@link #getStringBuffer} to get the current string state.
- *
- * If the object is null, return the style's nullText
- *
- * @return the String toString
- */
- @Override
- public String toString() {
- if (this.getObject() == null) {
- this.getStringBuffer().append(this.getStyle().getNullText());
- } else {
- style.appendEnd(this.getStringBuffer(), this.getObject());
- }
- return this.getStringBuffer().toString();
- }
-
- /**
- * Returns the String that was build as an object representation. The
- * default implementation utilizes the {@link #toString()} implementation.
- *
- * @return the String toString
- *
- * @see #toString()
- *
- * @since 3.0
- */
- @Override
- public String build() {
- return toString();
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringExclude.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringExclude.java
deleted file mode 100644
index 066f966f..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringExclude.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Use this annotation to exclude a field from being used by
- * the {@link ReflectionToStringBuilder}.
- *
- * @since 3.5
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface ToStringExclude {
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringStyle.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringStyle.java
deleted file mode 100644
index adff53e1..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringStyle.java
+++ /dev/null
@@ -1,2633 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.io.Serializable;
-import java.lang.reflect.Array;
-import java.util.Collection;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * Controls String formatting for {@link ToStringBuilder}.
- * The main public interface is always via ToStringBuilder.
- *
- * These classes are intended to be used as Singletons.
- * There is no need to instantiate a new style each time. A program
- * will generally use one of the predefined constants on this class.
- * Alternatively, the {@link StandardToStringStyle} class can be used
- * to set the individual settings. Thus most styles can be achieved
- * without subclassing.
- *
- * If required, a subclass can override as many or as few of the
- * methods as it requires. Each object type (from boolean
- * to long to Object to int[]) has
- * its own methods to output it. Most have two versions, detail and summary.
- *
- *
For example, the detail version of the array based methods will
- * output the whole array, whereas the summary method will just output
- * the array length.
- *
- * If you want to format the output of certain objects, such as dates, you
- * must create a subclass and override a method.
- *
- *
- * public class MyStyle extends ToStringStyle {
- * protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
- * if (value instanceof Date) {
- * value = new SimpleDateFormat("yyyy-MM-dd").format(value);
- * }
- * buffer.append(value);
- * }
- * }
- *
- *
- * @since 1.0
- */
-@SuppressWarnings("deprecation") // StringEscapeUtils
-public abstract class ToStringStyle implements Serializable {
-
- /**
- * Serialization version ID.
- */
- private static final long serialVersionUID = -2587890625525655916L;
-
- /**
- * The default toString style. Using the Person
- * example from {@link ToStringBuilder}, the output would look like this:
- *
- *
- * Person@182f0db[name=John Doe,age=33,smoker=false]
- *
- */
- public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
-
- /**
- * The multi line toString style. Using the Person
- * example from {@link ToStringBuilder}, the output would look like this:
- *
- *
- * Person@182f0db[
- * name=John Doe
- * age=33
- * smoker=false
- * ]
- *
- */
- public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
-
- /**
- * The no field names toString style. Using the
- * Person example from {@link ToStringBuilder}, the output
- * would look like this:
- *
- *
- * Person@182f0db[John Doe,33,false]
- *
- */
- public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
-
- /**
- * The short prefix toString style. Using the Person example
- * from {@link ToStringBuilder}, the output would look like this:
- *
- *
- * Person[name=John Doe,age=33,smoker=false]
- *
- *
- * @since 2.1
- */
- public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
-
- /**
- * The simple toString style. Using the Person
- * example from {@link ToStringBuilder}, the output would look like this:
- *
- *
- * John Doe,33,false
- *
- */
- public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
-
- /**
- * The no class name toString style. Using the Person
- * example from {@link ToStringBuilder}, the output would look like this:
- *
- *
- * [name=John Doe,age=33,smoker=false]
- *
- *
- * @since 3.4
- */
- public static final ToStringStyle NO_CLASS_NAME_STYLE = new NoClassNameToStringStyle();
-
- /**
- * The JSON toString style. Using the Person example from
- * {@link ToStringBuilder}, the output would look like this:
- *
- *
- * {"name": "John Doe", "age": 33, "smoker": true}
- *
- *
- * Note: Since field names are mandatory in JSON, this
- * ToStringStyle will throw an {@link UnsupportedOperationException} if no
- * field name is passed in while appending. Furthermore This ToStringStyle
- * will only generate valid JSON if referenced objects also produce JSON
- * when calling {@code toString()} on them.
- *
- * @since 3.4
- * @see json.org
- */
- public static final ToStringStyle JSON_STYLE = new JsonToStringStyle();
-
- /**
- *
- * A registry of objects used by reflectionToString methods
- * to detect cyclical object references and avoid infinite loops.
- *
- */
- private static final ThreadLocal> REGISTRY =
- new ThreadLocal<>();
- /*
- * Note that objects of this class are generally shared between threads, so
- * an instance variable would not be suitable here.
- *
- * In normal use the registry should always be left empty, because the caller
- * should call toString() which will clean up.
- *
- * See LANG-792
- */
-
- /**
- *
- * Returns the registry of objects being traversed by the reflectionToString
- * methods in the current thread.
- *
- *
- * @return Set the registry of objects being traversed
- */
- static Map getRegistry() {
- return REGISTRY.get();
- }
-
- /**
- *
- * Returns true if the registry contains the given object.
- * Used by the reflection methods to avoid infinite loops.
- *
- *
- * @param value
- * The object to lookup in the registry.
- * @return boolean true if the registry contains the given
- * object.
- */
- static boolean isRegistered(final Object value) {
- final Map m = getRegistry();
- return m != null && m.containsKey(value);
- }
-
- /**
- *
- * Registers the given object. Used by the reflection methods to avoid
- * infinite loops.
- *
- *
- * @param value
- * The object to register.
- */
- static void register(final Object value) {
- if (value != null) {
- final Map m = getRegistry();
- if (m == null) {
- REGISTRY.set(new WeakHashMap<>());
- }
- getRegistry().put(value, null);
- }
- }
-
- /**
- *
- * Unregisters the given object.
- *
- *
- *
- * Used by the reflection methods to avoid infinite loops.
- *
- *
- * @param value
- * The object to unregister.
- */
- static void unregister(final Object value) {
- if (value != null) {
- final Map m = getRegistry();
- if (m != null) {
- m.remove(value);
- if (m.isEmpty()) {
- REGISTRY.remove();
- }
- }
- }
- }
-
- /**
- * Whether to use the field names, the default is true.
- */
- private boolean useFieldNames = true;
-
- /**
- * Whether to use the class name, the default is true.
- */
- private boolean useClassName = true;
-
- /**
- * Whether to use short class names, the default is false.
- */
- private boolean useShortClassName = false;
-
- /**
- * Whether to use the identity hash code, the default is true.
- */
- private boolean useIdentityHashCode = true;
-
- /**
- * The content start '['.
- */
- private String contentStart = "[";
-
- /**
- * The content end ']'.
- */
- private String contentEnd = "]";
-
- /**
- * The field name value separator '='.
- */
- private String fieldNameValueSeparator = "=";
-
- /**
- * Whether the field separator should be added before any other fields.
- */
- private boolean fieldSeparatorAtStart = false;
-
- /**
- * Whether the field separator should be added after any other fields.
- */
- private boolean fieldSeparatorAtEnd = false;
-
- /**
- * The field separator ','.
- */
- private String fieldSeparator = ",";
-
- /**
- * The array start '{'.
- */
- private String arrayStart = "{";
-
- /**
- * The array separator ','.
- */
- private String arraySeparator = ",";
-
- /**
- * The detail for array content.
- */
- private boolean arrayContentDetail = true;
-
- /**
- * The array end '}'.
- */
- private String arrayEnd = "}";
-
- /**
- * The value to use when fullDetail is null,
- * the default value is true.
- */
- private boolean defaultFullDetail = true;
-
- /**
- * The null text '<null>'.
- */
- private String nullText = "";
-
- /**
- * The summary size text start '<size'.
- */
- private String sizeStartText = "'>'.
- */
- private String sizeEndText = ">";
-
- /**
- * The summary object text start '<'.
- */
- private String summaryObjectStartText = "<";
-
- /**
- * The summary object text start '>'.
- */
- private String summaryObjectEndText = ">";
-
- //----------------------------------------------------------------------------
-
- /**
- * Constructor.
- */
- protected ToStringStyle() {
- super();
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString the superclass toString.
- * NOTE: It assumes that the toString has been created from the same ToStringStyle.
- *
- * A null superToString is ignored.
- *
- * @param buffer the StringBuffer to populate
- * @param superToString the super.toString()
- * @since 2.0
- */
- public void appendSuper(final StringBuffer buffer, final String superToString) {
- appendToString(buffer, superToString);
- }
-
- /**
- * Append to the toString another toString.
- * NOTE: It assumes that the toString has been created from the same ToStringStyle.
- *
- * A null toString is ignored.
- *
- * @param buffer the StringBuffer to populate
- * @param toString the additional toString
- * @since 2.0
- */
- public void appendToString(final StringBuffer buffer, final String toString) {
- if (toString != null) {
- final int pos1 = toString.indexOf(contentStart) + contentStart.length();
- final int pos2 = toString.lastIndexOf(contentEnd);
- if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) {
- if (fieldSeparatorAtStart) {
- removeLastFieldSeparator(buffer);
- }
- buffer.append(toString, pos1, pos2);
- appendFieldSeparator(buffer);
- }
- }
- }
-
- /**
- * Append to the toString the start of data indicator.
- *
- * @param buffer the StringBuffer to populate
- * @param object the Object to build a toString for
- */
- public void appendStart(final StringBuffer buffer, final Object object) {
- if (object != null) {
- appendClassName(buffer, object);
- appendIdentityHashCode(buffer, object);
- appendContentStart(buffer);
- if (fieldSeparatorAtStart) {
- appendFieldSeparator(buffer);
- }
- }
- }
-
- /**
- * Append to the toString the end of data indicator.
- *
- * @param buffer the StringBuffer to populate
- * @param object the Object to build a
- * toString for.
- */
- public void appendEnd(final StringBuffer buffer, final Object object) {
- if (!this.fieldSeparatorAtEnd) {
- removeLastFieldSeparator(buffer);
- }
- appendContentEnd(buffer);
- unregister(object);
- }
-
- /**
- * Remove the last field separator from the buffer.
- *
- * @param buffer the StringBuffer to populate
- * @since 2.0
- */
- protected void removeLastFieldSeparator(final StringBuffer buffer) {
- final int len = buffer.length();
- final int sepLen = fieldSeparator.length();
- if (len > 0 && sepLen > 0 && len >= sepLen) {
- boolean match = true;
- for (int i = 0; i < sepLen; i++) {
- if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) {
- match = false;
- break;
- }
- }
- if (match) {
- buffer.setLength(len - sepLen);
- }
- }
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an Object
- * value, printing the full toString of the
- * Object passed in.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final Object value, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (value == null) {
- appendNullText(buffer, fieldName);
-
- } else {
- appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString an Object,
- * correctly interpreting its type.
- *
- * This method performs the main lookup by Class type to correctly
- * route arrays, Collections, Maps and
- * Objects to the appropriate method.
- *
- * Either detail or summary views can be specified.
- *
- * If a cycle is detected, an object will be appended with the
- * Object.toString() format.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString,
- * not null
- * @param detail output detail or not
- */
- protected void appendInternal(final StringBuffer buffer, final String fieldName, final Object value, final boolean detail) {
- if (isRegistered(value)
- && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
- appendCyclicObject(buffer, fieldName, value);
- return;
- }
-
- register(value);
-
- try {
- if (value instanceof Collection>) {
- if (detail) {
- appendDetail(buffer, fieldName, (Collection>) value);
- } else {
- appendSummarySize(buffer, fieldName, ((Collection>) value).size());
- }
-
- } else if (value instanceof Map, ?>) {
- if (detail) {
- appendDetail(buffer, fieldName, (Map, ?>) value);
- } else {
- appendSummarySize(buffer, fieldName, ((Map, ?>) value).size());
- }
-
- } else if (value instanceof long[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (long[]) value);
- } else {
- appendSummary(buffer, fieldName, (long[]) value);
- }
-
- } else if (value instanceof int[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (int[]) value);
- } else {
- appendSummary(buffer, fieldName, (int[]) value);
- }
-
- } else if (value instanceof short[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (short[]) value);
- } else {
- appendSummary(buffer, fieldName, (short[]) value);
- }
-
- } else if (value instanceof byte[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (byte[]) value);
- } else {
- appendSummary(buffer, fieldName, (byte[]) value);
- }
-
- } else if (value instanceof char[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (char[]) value);
- } else {
- appendSummary(buffer, fieldName, (char[]) value);
- }
-
- } else if (value instanceof double[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (double[]) value);
- } else {
- appendSummary(buffer, fieldName, (double[]) value);
- }
-
- } else if (value instanceof float[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (float[]) value);
- } else {
- appendSummary(buffer, fieldName, (float[]) value);
- }
-
- } else if (value instanceof boolean[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (boolean[]) value);
- } else {
- appendSummary(buffer, fieldName, (boolean[]) value);
- }
-
- } else if (value.getClass().isArray()) {
- if (detail) {
- appendDetail(buffer, fieldName, (Object[]) value);
- } else {
- appendSummary(buffer, fieldName, (Object[]) value);
- }
-
- } else {
- if (detail) {
- appendDetail(buffer, fieldName, value);
- } else {
- appendSummary(buffer, fieldName, value);
- }
- }
- } finally {
- unregister(value);
- }
- }
-
- /**
- * Append to the toString an Object
- * value that has been detected to participate in a cycle. This
- * implementation will print the standard string value of the value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString,
- * not null
- *
- * @since 2.2
- */
- protected void appendCyclicObject(final StringBuffer buffer, final String fieldName, final Object value) {
- ObjectUtils.identityToString(buffer, value);
- }
-
- /**
- * Append to the toString an Object
- * value, printing the full detail of the Object.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) {
- buffer.append(value);
- }
-
- /**
- * Append to the toString a Collection.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param coll the Collection to add to the
- * toString, not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final Collection> coll) {
- buffer.append(coll);
- }
-
- /**
- * Append to the toString a Map.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param map the Map to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final Map, ?> map) {
- buffer.append(map);
- }
-
- /**
- * Append to the toString an Object
- * value, printing a summary of the Object.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final Object value) {
- buffer.append(summaryObjectStartText);
- buffer.append(getShortClassName(value.getClass()));
- buffer.append(summaryObjectEndText);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a long
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final long value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a long
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final long value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an int
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final int value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString an int
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final int value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a short
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final short value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a short
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final short value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a byte
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final byte value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a byte
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a char
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final char value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a char
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final char value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a double
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final double value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a double
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final double value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a float
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final float value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a float
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final float value) {
- buffer.append(value);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a boolean
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param value the value to add to the toString
- */
- public void append(final StringBuffer buffer, final String fieldName, final boolean value) {
- appendFieldStart(buffer, fieldName);
- appendDetail(buffer, fieldName, value);
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString a boolean
- * value.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param value the value to add to the toString
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean value) {
- buffer.append(value);
- }
-
- /**
- * Append to the toString an Object
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final Object[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString the detail of an
- * Object array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- final Object item = array[i];
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- if (item == null) {
- appendNullText(buffer, fieldName);
-
- } else {
- appendInternal(buffer, fieldName, item, arrayContentDetail);
- }
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString the detail of an array type.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- * @since 2.0
- */
- protected void reflectionAppendArrayDetail(final StringBuffer buffer, final String fieldName, final Object array) {
- buffer.append(arrayStart);
- final int length = Array.getLength(array);
- for (int i = 0; i < length; i++) {
- final Object item = Array.get(array, i);
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- if (item == null) {
- appendNullText(buffer, fieldName);
-
- } else {
- appendInternal(buffer, fieldName, item, arrayContentDetail);
- }
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of an
- * Object array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final Object[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a long
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final long[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * long array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final long[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * long array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final long[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString an int
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final int[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of an
- * int array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final int[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of an
- * int array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final int[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a short
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final short[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * short array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final short[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * short array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final short[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a byte
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final byte[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * byte array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final byte[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * byte array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final byte[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a char
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final char[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * char array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final char[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * char array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final char[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a double
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final double[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * double array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final double[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * double array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final double[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a float
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final float[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * float array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final float[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * float array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final float[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString a boolean
- * array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- * @param array the array to add to the toString
- * @param fullDetail true for detail, false
- * for summary info, null for style decides
- */
- public void append(final StringBuffer buffer, final String fieldName, final boolean[] array, final Boolean fullDetail) {
- appendFieldStart(buffer, fieldName);
-
- if (array == null) {
- appendNullText(buffer, fieldName);
-
- } else if (isFullDetail(fullDetail)) {
- appendDetail(buffer, fieldName, array);
-
- } else {
- appendSummary(buffer, fieldName, array);
- }
-
- appendFieldEnd(buffer, fieldName);
- }
-
- /**
- * Append to the toString the detail of a
- * boolean array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final boolean[] array) {
- buffer.append(arrayStart);
- for (int i = 0; i < array.length; i++) {
- if (i > 0) {
- buffer.append(arraySeparator);
- }
- appendDetail(buffer, fieldName, array[i]);
- }
- buffer.append(arrayEnd);
- }
-
- /**
- * Append to the toString a summary of a
- * boolean array.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param array the array to add to the toString,
- * not null
- */
- protected void appendSummary(final StringBuffer buffer, final String fieldName, final boolean[] array) {
- appendSummarySize(buffer, fieldName, array.length);
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Append to the toString the class name.
- *
- * @param buffer the StringBuffer to populate
- * @param object the Object whose name to output
- */
- protected void appendClassName(final StringBuffer buffer, final Object object) {
- if (useClassName && object != null) {
- register(object);
- if (useShortClassName) {
- buffer.append(getShortClassName(object.getClass()));
- } else {
- buffer.append(object.getClass().getName());
- }
- }
- }
-
- /**
- * Append the {@link System#identityHashCode(Object)}.
- *
- * @param buffer the StringBuffer to populate
- * @param object the Object whose id to output
- */
- protected void appendIdentityHashCode(final StringBuffer buffer, final Object object) {
- if (this.isUseIdentityHashCode() && object!=null) {
- register(object);
- buffer.append('@');
- buffer.append(Integer.toHexString(System.identityHashCode(object)));
- }
- }
-
- /**
- * Append to the toString the content start.
- *
- * @param buffer the StringBuffer to populate
- */
- protected void appendContentStart(final StringBuffer buffer) {
- buffer.append(contentStart);
- }
-
- /**
- * Append to the toString the content end.
- *
- * @param buffer the StringBuffer to populate
- */
- protected void appendContentEnd(final StringBuffer buffer) {
- buffer.append(contentEnd);
- }
-
- /**
- * Append to the toString an indicator for null.
- *
- * The default indicator is '<null>'.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- */
- protected void appendNullText(final StringBuffer buffer, final String fieldName) {
- buffer.append(nullText);
- }
-
- /**
- * Append to the toString the field separator.
- *
- * @param buffer the StringBuffer to populate
- */
- protected void appendFieldSeparator(final StringBuffer buffer) {
- buffer.append(fieldSeparator);
- }
-
- /**
- * Append to the toString the field start.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name
- */
- protected void appendFieldStart(final StringBuffer buffer, final String fieldName) {
- if (useFieldNames && fieldName != null) {
- buffer.append(fieldName);
- buffer.append(fieldNameValueSeparator);
- }
- }
-
- /**
- * Append to the toString the field end.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- */
- protected void appendFieldEnd(final StringBuffer buffer, final String fieldName) {
- appendFieldSeparator(buffer);
- }
-
- /**
- * Append to the toString a size summary.
- *
- * The size summary is used to summarize the contents of
- * Collections, Maps and arrays.
- *
- * The output consists of a prefix, the passed in size
- * and a suffix.
- *
- * The default format is '<size=n>'.
- *
- * @param buffer the StringBuffer to populate
- * @param fieldName the field name, typically not used as already appended
- * @param size the size to append
- */
- protected void appendSummarySize(final StringBuffer buffer, final String fieldName, final int size) {
- buffer.append(sizeStartText);
- buffer.append(size);
- buffer.append(sizeEndText);
- }
-
- /**
- * Is this field to be output in full detail.
- *
- * This method converts a detail request into a detail level.
- * The calling code may request full detail (true),
- * but a subclass might ignore that and always return
- * false. The calling code may pass in
- * null indicating that it doesn't care about
- * the detail level. In this case the default detail level is
- * used.
- *
- * @param fullDetailRequest the detail level requested
- * @return whether full detail is to be shown
- */
- protected boolean isFullDetail(final Boolean fullDetailRequest) {
- if (fullDetailRequest == null) {
- return defaultFullDetail;
- }
- return fullDetailRequest.booleanValue();
- }
-
- /**
- * Gets the short class name for a class.
- *
- * The short class name is the classname excluding
- * the package name.
- *
- * @param cls the Class to get the short name of
- * @return the short name
- */
- protected String getShortClassName(final Class> cls) {
- return ClassUtils.getShortClassName(cls);
- }
-
- // Setters and getters for the customizable parts of the style
- // These methods are not expected to be overridden, except to make public
- // (They are not public so that immutable subclasses can be written)
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to use the class name.
- *
- * @return the current useClassName flag
- */
- protected boolean isUseClassName() {
- return useClassName;
- }
-
- /**
- * Sets whether to use the class name.
- *
- * @param useClassName the new useClassName flag
- */
- protected void setUseClassName(final boolean useClassName) {
- this.useClassName = useClassName;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to output short or long class names.
- *
- * @return the current useShortClassName flag
- * @since 2.0
- */
- protected boolean isUseShortClassName() {
- return useShortClassName;
- }
-
- /**
- * Sets whether to output short or long class names.
- *
- * @param useShortClassName the new useShortClassName flag
- * @since 2.0
- */
- protected void setUseShortClassName(final boolean useShortClassName) {
- this.useShortClassName = useShortClassName;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to use the identity hash code.
- *
- * @return the current useIdentityHashCode flag
- */
- protected boolean isUseIdentityHashCode() {
- return useIdentityHashCode;
- }
-
- /**
- * Sets whether to use the identity hash code.
- *
- * @param useIdentityHashCode the new useIdentityHashCode flag
- */
- protected void setUseIdentityHashCode(final boolean useIdentityHashCode) {
- this.useIdentityHashCode = useIdentityHashCode;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to use the field names passed in.
- *
- * @return the current useFieldNames flag
- */
- protected boolean isUseFieldNames() {
- return useFieldNames;
- }
-
- /**
- * Sets whether to use the field names passed in.
- *
- * @param useFieldNames the new useFieldNames flag
- */
- protected void setUseFieldNames(final boolean useFieldNames) {
- this.useFieldNames = useFieldNames;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to use full detail when the caller doesn't
- * specify.
- *
- * @return the current defaultFullDetail flag
- */
- protected boolean isDefaultFullDetail() {
- return defaultFullDetail;
- }
-
- /**
- * Sets whether to use full detail when the caller doesn't
- * specify.
- *
- * @param defaultFullDetail the new defaultFullDetail flag
- */
- protected void setDefaultFullDetail(final boolean defaultFullDetail) {
- this.defaultFullDetail = defaultFullDetail;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether to output array content detail.
- *
- * @return the current array content detail setting
- */
- protected boolean isArrayContentDetail() {
- return arrayContentDetail;
- }
-
- /**
- * Sets whether to output array content detail.
- *
- * @param arrayContentDetail the new arrayContentDetail flag
- */
- protected void setArrayContentDetail(final boolean arrayContentDetail) {
- this.arrayContentDetail = arrayContentDetail;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the array start text.
- *
- * @return the current array start text
- */
- protected String getArrayStart() {
- return arrayStart;
- }
-
- /**
- * Sets the array start text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param arrayStart the new array start text
- */
- protected void setArrayStart(String arrayStart) {
- if (arrayStart == null) {
- arrayStart = StringUtils.EMPTY;
- }
- this.arrayStart = arrayStart;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the array end text.
- *
- * @return the current array end text
- */
- protected String getArrayEnd() {
- return arrayEnd;
- }
-
- /**
- * Sets the array end text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param arrayEnd the new array end text
- */
- protected void setArrayEnd(String arrayEnd) {
- if (arrayEnd == null) {
- arrayEnd = StringUtils.EMPTY;
- }
- this.arrayEnd = arrayEnd;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the array separator text.
- *
- * @return the current array separator text
- */
- protected String getArraySeparator() {
- return arraySeparator;
- }
-
- /**
- * Sets the array separator text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param arraySeparator the new array separator text
- */
- protected void setArraySeparator(String arraySeparator) {
- if (arraySeparator == null) {
- arraySeparator = StringUtils.EMPTY;
- }
- this.arraySeparator = arraySeparator;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the content start text.
- *
- * @return the current content start text
- */
- protected String getContentStart() {
- return contentStart;
- }
-
- /**
- * Sets the content start text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param contentStart the new content start text
- */
- protected void setContentStart(String contentStart) {
- if (contentStart == null) {
- contentStart = StringUtils.EMPTY;
- }
- this.contentStart = contentStart;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the content end text.
- *
- * @return the current content end text
- */
- protected String getContentEnd() {
- return contentEnd;
- }
-
- /**
- * Sets the content end text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param contentEnd the new content end text
- */
- protected void setContentEnd(String contentEnd) {
- if (contentEnd == null) {
- contentEnd = StringUtils.EMPTY;
- }
- this.contentEnd = contentEnd;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the field name value separator text.
- *
- * @return the current field name value separator text
- */
- protected String getFieldNameValueSeparator() {
- return fieldNameValueSeparator;
- }
-
- /**
- * Sets the field name value separator text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param fieldNameValueSeparator the new field name value separator text
- */
- protected void setFieldNameValueSeparator(String fieldNameValueSeparator) {
- if (fieldNameValueSeparator == null) {
- fieldNameValueSeparator = StringUtils.EMPTY;
- }
- this.fieldNameValueSeparator = fieldNameValueSeparator;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the field separator text.
- *
- * @return the current field separator text
- */
- protected String getFieldSeparator() {
- return fieldSeparator;
- }
-
- /**
- * Sets the field separator text.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param fieldSeparator the new field separator text
- */
- protected void setFieldSeparator(String fieldSeparator) {
- if (fieldSeparator == null) {
- fieldSeparator = StringUtils.EMPTY;
- }
- this.fieldSeparator = fieldSeparator;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether the field separator should be added at the start
- * of each buffer.
- *
- * @return the fieldSeparatorAtStart flag
- * @since 2.0
- */
- protected boolean isFieldSeparatorAtStart() {
- return fieldSeparatorAtStart;
- }
-
- /**
- * Sets whether the field separator should be added at the start
- * of each buffer.
- *
- * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag
- * @since 2.0
- */
- protected void setFieldSeparatorAtStart(final boolean fieldSeparatorAtStart) {
- this.fieldSeparatorAtStart = fieldSeparatorAtStart;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets whether the field separator should be added at the end
- * of each buffer.
- *
- * @return fieldSeparatorAtEnd flag
- * @since 2.0
- */
- protected boolean isFieldSeparatorAtEnd() {
- return fieldSeparatorAtEnd;
- }
-
- /**
- * Sets whether the field separator should be added at the end
- * of each buffer.
- *
- * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag
- * @since 2.0
- */
- protected void setFieldSeparatorAtEnd(final boolean fieldSeparatorAtEnd) {
- this.fieldSeparatorAtEnd = fieldSeparatorAtEnd;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the text to output when null found.
- *
- * @return the current text to output when null found
- */
- protected String getNullText() {
- return nullText;
- }
-
- /**
- * Sets the text to output when null found.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param nullText the new text to output when null found
- */
- protected void setNullText(String nullText) {
- if (nullText == null) {
- nullText = StringUtils.EMPTY;
- }
- this.nullText = nullText;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the start text to output when a Collection,
- * Map or array size is output.
- *
- * This is output before the size value.
- *
- * @return the current start of size text
- */
- protected String getSizeStartText() {
- return sizeStartText;
- }
-
- /**
- * Sets the start text to output when a Collection,
- * Map or array size is output.
- *
- * This is output before the size value.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param sizeStartText the new start of size text
- */
- protected void setSizeStartText(String sizeStartText) {
- if (sizeStartText == null) {
- sizeStartText = StringUtils.EMPTY;
- }
- this.sizeStartText = sizeStartText;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the end text to output when a Collection,
- * Map or array size is output.
- *
- * This is output after the size value.
- *
- * @return the current end of size text
- */
- protected String getSizeEndText() {
- return sizeEndText;
- }
-
- /**
- * Sets the end text to output when a Collection,
- * Map or array size is output.
- *
- * This is output after the size value.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param sizeEndText the new end of size text
- */
- protected void setSizeEndText(String sizeEndText) {
- if (sizeEndText == null) {
- sizeEndText = StringUtils.EMPTY;
- }
- this.sizeEndText = sizeEndText;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the start text to output when an Object is
- * output in summary mode.
- *
- * This is output before the size value.
- *
- * @return the current start of summary text
- */
- protected String getSummaryObjectStartText() {
- return summaryObjectStartText;
- }
-
- /**
- * Sets the start text to output when an Object is
- * output in summary mode.
- *
- * This is output before the size value.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param summaryObjectStartText the new start of summary text
- */
- protected void setSummaryObjectStartText(String summaryObjectStartText) {
- if (summaryObjectStartText == null) {
- summaryObjectStartText = StringUtils.EMPTY;
- }
- this.summaryObjectStartText = summaryObjectStartText;
- }
-
- //---------------------------------------------------------------------
-
- /**
- * Gets the end text to output when an Object is
- * output in summary mode.
- *
- * This is output after the size value.
- *
- * @return the current end of summary text
- */
- protected String getSummaryObjectEndText() {
- return summaryObjectEndText;
- }
-
- /**
- * Sets the end text to output when an Object is
- * output in summary mode.
- *
- * This is output after the size value.
- *
- * null is accepted, but will be converted to
- * an empty String.
- *
- * @param summaryObjectEndText the new end of summary text
- */
- protected void setSummaryObjectEndText(String summaryObjectEndText) {
- if (summaryObjectEndText == null) {
- summaryObjectEndText = StringUtils.EMPTY;
- }
- this.summaryObjectEndText = summaryObjectEndText;
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * Default ToStringStyle.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class DefaultToStringStyle extends ToStringStyle {
-
- /**
- * Required for serialization support.
- *
- * @see Serializable
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- DefaultToStringStyle() {
- super();
- }
-
- /**
- * Ensure Singleton after serialization.
- *
- * @return the singleton
- */
- private Object readResolve() {
- return DEFAULT_STYLE;
- }
-
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * ToStringStyle that does not print out
- * the field names.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class NoFieldNameToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- /**
- *
Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- NoFieldNameToStringStyle() {
- super();
- this.setUseFieldNames(false);
- }
-
- /**
- * Ensure Singleton after serialization.
- *
- * @return the singleton
- */
- private Object readResolve() {
- return NO_FIELD_NAMES_STYLE;
- }
-
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * ToStringStyle that prints out the short
- * class name and no identity hashcode.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class ShortPrefixToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- ShortPrefixToStringStyle() {
- super();
- this.setUseShortClassName(true);
- this.setUseIdentityHashCode(false);
- }
-
- /**
- * Ensure Singleton after serialization.
- * @return the singleton
- */
- private Object readResolve() {
- return SHORT_PREFIX_STYLE;
- }
-
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * ToStringStyle that does not print out the
- * classname, identity hashcode, content start or field name.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class SimpleToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- SimpleToStringStyle() {
- super();
- this.setUseClassName(false);
- this.setUseIdentityHashCode(false);
- this.setUseFieldNames(false);
- this.setContentStart(StringUtils.EMPTY);
- this.setContentEnd(StringUtils.EMPTY);
- }
-
- /**
- * Ensure Singleton after serialization.
- * @return the singleton
- */
- private Object readResolve() {
- return SIMPLE_STYLE;
- }
-
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * ToStringStyle that outputs on multiple lines.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class MultiLineToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- MultiLineToStringStyle() {
- super();
- this.setContentStart("[");
- this.setFieldSeparator(System.lineSeparator() + " ");
- this.setFieldSeparatorAtStart(true);
- this.setContentEnd(System.lineSeparator() + "]");
- }
-
- /**
- * Ensure Singleton after serialization.
- *
- * @return the singleton
- */
- private Object readResolve() {
- return MULTI_LINE_STYLE;
- }
-
- }
-
- //----------------------------------------------------------------------------
-
- /**
- * ToStringStyle that does not print out the classname
- * and identity hash code but prints content start and field names.
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- */
- private static final class NoClassNameToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- *
- * Use the static constant rather than instantiating.
- */
- NoClassNameToStringStyle() {
- super();
- this.setUseClassName(false);
- this.setUseIdentityHashCode(false);
- }
-
- /**
- * Ensure Singleton after serialization.
- *
- * @return the singleton
- */
- private Object readResolve() {
- return NO_CLASS_NAME_STYLE;
- }
-
- }
-
- // ----------------------------------------------------------------------------
-
- /**
- *
- * ToStringStyle that outputs with JSON format.
- *
- *
- *
- * This is an inner class rather than using
- * StandardToStringStyle to ensure its immutability.
- *
- *
- * @since 3.4
- * @see json.org
- */
- private static final class JsonToStringStyle extends ToStringStyle {
-
- private static final long serialVersionUID = 1L;
-
- private static final String FIELD_NAME_QUOTE = "\"";
-
- /**
- *
- * Constructor.
- *
- *
- *
- * Use the static constant rather than instantiating.
- *
- */
- JsonToStringStyle() {
- super();
-
- this.setUseClassName(false);
- this.setUseIdentityHashCode(false);
-
- this.setContentStart("{");
- this.setContentEnd("}");
-
- this.setArrayStart("[");
- this.setArrayEnd("]");
-
- this.setFieldSeparator(",");
- this.setFieldNameValueSeparator(":");
-
- this.setNullText("null");
-
- this.setSummaryObjectStartText("\"<");
- this.setSummaryObjectEndText(">\"");
-
- this.setSizeStartText("\"\"");
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName,
- final Object[] array, final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName, final long[] array,
- final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName, final int[] array,
- final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName,
- final short[] array, final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName, final byte[] array,
- final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName, final char[] array,
- final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName,
- final double[] array, final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName,
- final float[] array, final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName,
- final boolean[] array, final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, array, fullDetail);
- }
-
- @Override
- public void append(final StringBuffer buffer, final String fieldName, final Object value,
- final Boolean fullDetail) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
- if (!isFullDetail(fullDetail)){
- throw new UnsupportedOperationException(
- "FullDetail must be true when using JsonToStringStyle");
- }
-
- super.append(buffer, fieldName, value, fullDetail);
- }
-
- @Override
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final char value) {
- appendValueAsString(buffer, String.valueOf(value));
- }
-
- @Override
- protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) {
-
- if (value == null) {
- appendNullText(buffer, fieldName);
- return;
- }
-
- if (value instanceof String || value instanceof Character) {
- appendValueAsString(buffer, value.toString());
- return;
- }
-
- if (value instanceof Number || value instanceof Boolean) {
- buffer.append(value);
- return;
- }
-
- final String valueAsString = value.toString();
- if (isJsonObject(valueAsString) || isJsonArray(valueAsString)) {
- buffer.append(value);
- return;
- }
-
- appendDetail(buffer, fieldName, valueAsString);
- }
-
- private boolean isJsonArray(final String valueAsString) {
- return valueAsString.startsWith(getArrayStart())
- && valueAsString.endsWith(getArrayEnd());
- }
-
- private boolean isJsonObject(final String valueAsString) {
- return valueAsString.startsWith(getContentStart())
- && valueAsString.endsWith(getContentEnd());
- }
-
- /**
- * Appends the given String enclosed in double-quotes to the given StringBuffer.
- *
- * @param buffer the StringBuffer to append the value to.
- * @param value the value to append.
- */
- private void appendValueAsString(final StringBuffer buffer, final String value) {
- buffer.append('"').append(StringEscapeUtils.escapeJson(value)).append('"');
- }
-
- @Override
- protected void appendFieldStart(final StringBuffer buffer, final String fieldName) {
-
- if (fieldName == null) {
- throw new UnsupportedOperationException(
- "Field names are mandatory when using JsonToStringStyle");
- }
-
- super.appendFieldStart(buffer, FIELD_NAME_QUOTE + StringEscapeUtils.escapeJson(fieldName)
- + FIELD_NAME_QUOTE);
- }
-
- /**
- *
- * Ensure Singleton after serialization.
- *
- *
- * @return the singleton
- */
- private Object readResolve() {
- return JSON_STYLE;
- }
-
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringSummary.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringSummary.java
deleted file mode 100644
index 24b7ff00..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/ToStringSummary.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package com.joyy.stringescape;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Use this annotation on the fields to get the summary instead of the detailed
- * information when using {@link ReflectionToStringBuilder}.
- *
- *
- * Notice that not all {@link ToStringStyle} implementations support the
- * appendSummary method.
- *
- *
- * @since 3.8
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface ToStringSummary {
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Validate.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Validate.java
deleted file mode 100644
index 2cd36dcf..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/Validate.java
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-/**
- * This class assists in validating arguments. The validation methods are
- * based along the following principles:
- *
- * An invalid {@code null} argument causes a {@link NullPointerException}.
- * A non-{@code null} argument causes an {@link IllegalArgumentException}.
- * An invalid index into an array/collection/map/string causes an {@link IndexOutOfBoundsException}.
- *
- *
- * All exceptions messages are
- * format strings
- * as defined by the Java platform. For example:
- *
- *
- * Validate.isTrue(i > 0, "The value must be greater than zero: %d", i);
- * Validate.notNull(surname, "The surname must not be %s", null);
- *
- *
- * #ThreadSafe#
- * @see String#format(String, Object...)
- * @since 2.0
- */
-public class Validate {
-
- private static final String DEFAULT_NOT_NAN_EX_MESSAGE =
- "The validated value is not a number";
- private static final String DEFAULT_FINITE_EX_MESSAGE =
- "The value is invalid: %f";
- private static final String DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE =
- "The value %s is not in the specified exclusive range of %s to %s";
- private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE =
- "The value %s is not in the specified inclusive range of %s to %s";
- private static final String DEFAULT_MATCHES_PATTERN_EX = "The string %s does not match the pattern %s";
- private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null";
- private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false";
- private static final String DEFAULT_NO_NULL_ELEMENTS_ARRAY_EX_MESSAGE =
- "The validated array contains null element at index: %d";
- private static final String DEFAULT_NO_NULL_ELEMENTS_COLLECTION_EX_MESSAGE =
- "The validated collection contains null element at index: %d";
- private static final String DEFAULT_NOT_BLANK_EX_MESSAGE = "The validated character sequence is blank";
- private static final String DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE = "The validated array is empty";
- private static final String DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE =
- "The validated character sequence is empty";
- private static final String DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE = "The validated collection is empty";
- private static final String DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE = "The validated map is empty";
- private static final String DEFAULT_VALID_INDEX_ARRAY_EX_MESSAGE = "The validated array index is invalid: %d";
- private static final String DEFAULT_VALID_INDEX_CHAR_SEQUENCE_EX_MESSAGE =
- "The validated character sequence index is invalid: %d";
- private static final String DEFAULT_VALID_INDEX_COLLECTION_EX_MESSAGE =
- "The validated collection index is invalid: %d";
- private static final String DEFAULT_VALID_STATE_EX_MESSAGE = "The validated state is false";
- private static final String DEFAULT_IS_ASSIGNABLE_EX_MESSAGE = "Cannot assign a %s to a %s";
- private static final String DEFAULT_IS_INSTANCE_OF_EX_MESSAGE = "Expected type: %s, actual: %s";
-
- /**
- * Constructor. This class should not normally be instantiated.
- */
- public Validate() {
- super();
- }
-
- // isTrue
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the argument condition is {@code true}; otherwise
- * throwing an exception with the specified message. This method is useful when
- * validating according to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- * Validate.isTrue(i > 0.0, "The value must be greater than zero: %d", i);
- *
- * For performance reasons, the long value is passed as a separate parameter and
- * appended to the exception message only in the case of an error.
- *
- * @param expression the boolean expression to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param value the value to append to the message when invalid
- * @throws IllegalArgumentException if expression is {@code false}
- * @see #isTrue(boolean)
- * @see #isTrue(boolean, String, double)
- * @see #isTrue(boolean, String, Object...)
- */
- public static void isTrue(final boolean expression, final String message, final long value) {
- if (!expression) {
- throw new IllegalArgumentException(String.format(message, Long.valueOf(value)));
- }
- }
-
- /**
- * Validate that the argument condition is {@code true}; otherwise
- * throwing an exception with the specified message. This method is useful when
- * validating according to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- * Validate.isTrue(d > 0.0, "The value must be greater than zero: %s", d);
- *
- * For performance reasons, the double value is passed as a separate parameter and
- * appended to the exception message only in the case of an error.
- *
- * @param expression the boolean expression to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param value the value to append to the message when invalid
- * @throws IllegalArgumentException if expression is {@code false}
- * @see #isTrue(boolean)
- * @see #isTrue(boolean, String, long)
- * @see #isTrue(boolean, String, Object...)
- */
- public static void isTrue(final boolean expression, final String message, final double value) {
- if (!expression) {
- throw new IllegalArgumentException(String.format(message, Double.valueOf(value)));
- }
- }
-
- /**
- * Validate that the argument condition is {@code true}; otherwise
- * throwing an exception with the specified message. This method is useful when
- * validating according to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- *
- * Validate.isTrue(i >= min && i <= max, "The value must be between %d and %d", min, max);
- * Validate.isTrue(myObject.isOk(), "The object is not okay");
- *
- * @param expression the boolean expression to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if expression is {@code false}
- * @see #isTrue(boolean)
- * @see #isTrue(boolean, String, long)
- * @see #isTrue(boolean, String, double)
- */
- public static void isTrue(final boolean expression, final String message, final Object... values) {
- if (!expression) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- /**
- * Validate that the argument condition is {@code true}; otherwise
- * throwing an exception. This method is useful when validating according
- * to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- *
- * Validate.isTrue(i > 0);
- * Validate.isTrue(myObject.isOk());
- *
- * The message of the exception is "The validated expression is
- * false".
- *
- * @param expression the boolean expression to check
- * @throws IllegalArgumentException if expression is {@code false}
- * @see #isTrue(boolean, String, long)
- * @see #isTrue(boolean, String, double)
- * @see #isTrue(boolean, String, Object...)
- */
- public static void isTrue(final boolean expression) {
- if (!expression) {
- throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
- }
- }
-
- // notNull
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument is not {@code null};
- * otherwise throwing an exception.
- *
- *
Validate.notNull(myObject, "The object must not be null");
- *
- * The message of the exception is "The validated object is
- * null".
- *
- * @param the object type
- * @param object the object to check
- * @return the validated object (never {@code null} for method chaining)
- * @throws NullPointerException if the object is {@code null}
- * @see #notNull(Object, String, Object...)
- */
- public static T notNull(final T object) {
- return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE);
- }
-
- /**
- * Validate that the specified argument is not {@code null};
- * otherwise throwing an exception with the specified message.
- *
- *
Validate.notNull(myObject, "The object must not be null");
- *
- * @param the object type
- * @param object the object to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message
- * @return the validated object (never {@code null} for method chaining)
- * @throws NullPointerException if the object is {@code null}
- * @see #notNull(Object)
- */
- public static T notNull(final T object, final String message, final Object... values) {
- if (object == null) {
- throw new NullPointerException(String.format(message, values));
- }
- return object;
- }
-
- // notEmpty array
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument array is neither {@code null}
- * nor a length of zero (no elements); otherwise throwing an exception
- * with the specified message.
- *
- *
Validate.notEmpty(myArray, "The array must not be empty");
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated array (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if the array is empty
- * @see #notEmpty(Object[])
- */
- public static T[] notEmpty(final T[] array, final String message, final Object... values) {
- if (array == null) {
- throw new NullPointerException(String.format(message, values));
- }
- if (array.length == 0) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- return array;
- }
-
- /**
- * Validate that the specified argument array is neither {@code null}
- * nor a length of zero (no elements); otherwise throwing an exception.
- *
- *
Validate.notEmpty(myArray);
- *
- * The message in the exception is "The validated array is
- * empty".
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @return the validated array (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if the array is empty
- * @see #notEmpty(Object[], String, Object...)
- */
- public static T[] notEmpty(final T[] array) {
- return notEmpty(array, DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE);
- }
-
- // notEmpty collection
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument collection is neither {@code null}
- * nor a size of zero (no elements); otherwise throwing an exception
- * with the specified message.
- *
- *
Validate.notEmpty(myCollection, "The collection must not be empty");
- *
- * @param the collection type
- * @param collection the collection to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated collection (never {@code null} method for chaining)
- * @throws NullPointerException if the collection is {@code null}
- * @throws IllegalArgumentException if the collection is empty
- * @see #notEmpty(Object[])
- */
- public static > T notEmpty(final T collection, final String message, final Object... values) {
- if (collection == null) {
- throw new NullPointerException(String.format(message, values));
- }
- if (collection.isEmpty()) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- return collection;
- }
-
- /**
- * Validate that the specified argument collection is neither {@code null}
- * nor a size of zero (no elements); otherwise throwing an exception.
- *
- *
Validate.notEmpty(myCollection);
- *
- * The message in the exception is "The validated collection is
- * empty".
- *
- * @param the collection type
- * @param collection the collection to check, validated not null by this method
- * @return the validated collection (never {@code null} method for chaining)
- * @throws NullPointerException if the collection is {@code null}
- * @throws IllegalArgumentException if the collection is empty
- * @see #notEmpty(Collection, String, Object...)
- */
- public static > T notEmpty(final T collection) {
- return notEmpty(collection, DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE);
- }
-
- // notEmpty map
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument map is neither {@code null}
- * nor a size of zero (no elements); otherwise throwing an exception
- * with the specified message.
- *
- *
Validate.notEmpty(myMap, "The map must not be empty");
- *
- * @param the map type
- * @param map the map to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated map (never {@code null} method for chaining)
- * @throws NullPointerException if the map is {@code null}
- * @throws IllegalArgumentException if the map is empty
- * @see #notEmpty(Object[])
- */
- public static > T notEmpty(final T map, final String message, final Object... values) {
- if (map == null) {
- throw new NullPointerException(String.format(message, values));
- }
- if (map.isEmpty()) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- return map;
- }
-
- /**
- * Validate that the specified argument map is neither {@code null}
- * nor a size of zero (no elements); otherwise throwing an exception.
- *
- *
Validate.notEmpty(myMap);
- *
- * The message in the exception is "The validated map is
- * empty".
- *
- * @param the map type
- * @param map the map to check, validated not null by this method
- * @return the validated map (never {@code null} method for chaining)
- * @throws NullPointerException if the map is {@code null}
- * @throws IllegalArgumentException if the map is empty
- * @see #notEmpty(Map, String, Object...)
- */
- public static > T notEmpty(final T map) {
- return notEmpty(map, DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE);
- }
-
- // notEmpty string
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument character sequence is
- * neither {@code null} nor a length of zero (no characters);
- * otherwise throwing an exception with the specified message.
- *
- *
Validate.notEmpty(myString, "The string must not be empty");
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated character sequence (never {@code null} method for chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IllegalArgumentException if the character sequence is empty
- * @see #notEmpty(CharSequence)
- */
- public static T notEmpty(final T chars, final String message, final Object... values) {
- if (chars == null) {
- throw new NullPointerException(String.format(message, values));
- }
- if (chars.length() == 0) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- return chars;
- }
-
- /**
- * Validate that the specified argument character sequence is
- * neither {@code null} nor a length of zero (no characters);
- * otherwise throwing an exception with the specified message.
- *
- *
Validate.notEmpty(myString);
- *
- * The message in the exception is "The validated
- * character sequence is empty".
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @return the validated character sequence (never {@code null} method for chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IllegalArgumentException if the character sequence is empty
- * @see #notEmpty(CharSequence, String, Object...)
- */
- public static T notEmpty(final T chars) {
- return notEmpty(chars, DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE);
- }
-
- // notBlank string
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument character sequence is
- * neither {@code null}, a length of zero (no characters), empty
- * nor whitespace; otherwise throwing an exception with the specified
- * message.
- *
- *
Validate.notBlank(myString, "The string must not be blank");
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated character sequence (never {@code null} method for chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IllegalArgumentException if the character sequence is blank
- * @see #notBlank(CharSequence)
- *
- * @since 3.0
- */
- public static T notBlank(final T chars, final String message, final Object... values) {
- if (chars == null) {
- throw new NullPointerException(String.format(message, values));
- }
- if (StringUtils.isBlank(chars)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- return chars;
- }
-
- /**
- * Validate that the specified argument character sequence is
- * neither {@code null}, a length of zero (no characters), empty
- * nor whitespace; otherwise throwing an exception.
- *
- *
Validate.notBlank(myString);
- *
- * The message in the exception is "The validated character
- * sequence is blank".
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @return the validated character sequence (never {@code null} method for chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IllegalArgumentException if the character sequence is blank
- * @see #notBlank(CharSequence, String, Object...)
- *
- * @since 3.0
- */
- public static T notBlank(final T chars) {
- return notBlank(chars, DEFAULT_NOT_BLANK_EX_MESSAGE);
- }
-
- // noNullElements array
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument array is neither
- * {@code null} nor contains any elements that are {@code null};
- * otherwise throwing an exception with the specified message.
- *
- *
Validate.noNullElements(myArray, "The array contain null at position %d");
- *
- * If the array is {@code null}, then the message in the exception
- * is "The validated object is null".
- *
- * If the array has a {@code null} element, then the iteration
- * index of the invalid element is appended to the {@code values}
- * argument.
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated array (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if an element is {@code null}
- * @see #noNullElements(Object[])
- */
- public static T[] noNullElements(final T[] array, final String message, final Object... values) {
- notNull(array);
- for (int i = 0; i < array.length; i++) {
- if (array[i] == null) {
- final Object[] values2 = ArrayUtils.add(values, Integer.valueOf(i));
- throw new IllegalArgumentException(String.format(message, values2));
- }
- }
- return array;
- }
-
- /**
- * Validate that the specified argument array is neither
- * {@code null} nor contains any elements that are {@code null};
- * otherwise throwing an exception.
- *
- * Validate.noNullElements(myArray);
- *
- * If the array is {@code null}, then the message in the exception
- * is "The validated object is null".
- *
- * If the array has a {@code null} element, then the message in the
- * exception is "The validated array contains null element at index:
- * " followed by the index.
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @return the validated array (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if an element is {@code null}
- * @see #noNullElements(Object[], String, Object...)
- */
- public static T[] noNullElements(final T[] array) {
- return noNullElements(array, DEFAULT_NO_NULL_ELEMENTS_ARRAY_EX_MESSAGE);
- }
-
- // noNullElements iterable
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument iterable is neither
- * {@code null} nor contains any elements that are {@code null};
- * otherwise throwing an exception with the specified message.
- *
- *
Validate.noNullElements(myCollection, "The collection contains null at position %d");
- *
- * If the iterable is {@code null}, then the message in the exception
- * is "The validated object is null".
- *
- * If the iterable has a {@code null} element, then the iteration
- * index of the invalid element is appended to the {@code values}
- * argument.
- *
- * @param the iterable type
- * @param iterable the iterable to check, validated not null by this method
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated iterable (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if an element is {@code null}
- * @see #noNullElements(Iterable)
- */
- public static > T noNullElements(final T iterable, final String message, final Object... values) {
- notNull(iterable);
- int i = 0;
- for (final Iterator> it = iterable.iterator(); it.hasNext(); i++) {
- if (it.next() == null) {
- final Object[] values2 = ArrayUtils.addAll(values, Integer.valueOf(i));
- throw new IllegalArgumentException(String.format(message, values2));
- }
- }
- return iterable;
- }
-
- /**
- * Validate that the specified argument iterable is neither
- * {@code null} nor contains any elements that are {@code null};
- * otherwise throwing an exception.
- *
- *
Validate.noNullElements(myCollection);
- *
- * If the iterable is {@code null}, then the message in the exception
- * is "The validated object is null".
- *
- * If the array has a {@code null} element, then the message in the
- * exception is "The validated iterable contains null element at index:
- * " followed by the index.
- *
- * @param the iterable type
- * @param iterable the iterable to check, validated not null by this method
- * @return the validated iterable (never {@code null} method for chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IllegalArgumentException if an element is {@code null}
- * @see #noNullElements(Iterable, String, Object...)
- */
- public static > T noNullElements(final T iterable) {
- return noNullElements(iterable, DEFAULT_NO_NULL_ELEMENTS_COLLECTION_EX_MESSAGE);
- }
-
- // validIndex array
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the index is within the bounds of the argument
- * array; otherwise throwing an exception with the specified message.
- *
- * Validate.validIndex(myArray, 2, "The array index is invalid: ");
- *
- * If the array is {@code null}, then the message of the exception
- * is "The validated object is null".
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @param index the index to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated array (never {@code null} for method chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(Object[], int)
- *
- * @since 3.0
- */
- public static T[] validIndex(final T[] array, final int index, final String message, final Object... values) {
- notNull(array);
- if (index < 0 || index >= array.length) {
- throw new IndexOutOfBoundsException(String.format(message, values));
- }
- return array;
- }
-
- /**
- * Validates that the index is within the bounds of the argument
- * array; otherwise throwing an exception.
- *
- * Validate.validIndex(myArray, 2);
- *
- * If the array is {@code null}, then the message of the exception
- * is "The validated object is null".
- *
- * If the index is invalid, then the message of the exception is
- * "The validated array index is invalid: " followed by the
- * index.
- *
- * @param the array type
- * @param array the array to check, validated not null by this method
- * @param index the index to check
- * @return the validated array (never {@code null} for method chaining)
- * @throws NullPointerException if the array is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(Object[], int, String, Object...)
- *
- * @since 3.0
- */
- public static T[] validIndex(final T[] array, final int index) {
- return validIndex(array, index, DEFAULT_VALID_INDEX_ARRAY_EX_MESSAGE, Integer.valueOf(index));
- }
-
- // validIndex collection
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the index is within the bounds of the argument
- * collection; otherwise throwing an exception with the specified message.
- *
- * Validate.validIndex(myCollection, 2, "The collection index is invalid: ");
- *
- * If the collection is {@code null}, then the message of the
- * exception is "The validated object is null".
- *
- * @param the collection type
- * @param collection the collection to check, validated not null by this method
- * @param index the index to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated collection (never {@code null} for chaining)
- * @throws NullPointerException if the collection is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(Collection, int)
- *
- * @since 3.0
- */
- public static > T validIndex(final T collection, final int index, final String message, final Object... values) {
- notNull(collection);
- if (index < 0 || index >= collection.size()) {
- throw new IndexOutOfBoundsException(String.format(message, values));
- }
- return collection;
- }
-
- /**
- * Validates that the index is within the bounds of the argument
- * collection; otherwise throwing an exception.
- *
- * Validate.validIndex(myCollection, 2);
- *
- * If the index is invalid, then the message of the exception
- * is "The validated collection index is invalid: "
- * followed by the index.
- *
- * @param the collection type
- * @param collection the collection to check, validated not null by this method
- * @param index the index to check
- * @return the validated collection (never {@code null} for method chaining)
- * @throws NullPointerException if the collection is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(Collection, int, String, Object...)
- *
- * @since 3.0
- */
- public static > T validIndex(final T collection, final int index) {
- return validIndex(collection, index, DEFAULT_VALID_INDEX_COLLECTION_EX_MESSAGE, Integer.valueOf(index));
- }
-
- // validIndex string
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the index is within the bounds of the argument
- * character sequence; otherwise throwing an exception with the
- * specified message.
- *
- * Validate.validIndex(myStr, 2, "The string index is invalid: ");
- *
- * If the character sequence is {@code null}, then the message
- * of the exception is "The validated object is null".
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @param index the index to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @return the validated character sequence (never {@code null} for method chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(CharSequence, int)
- *
- * @since 3.0
- */
- public static T validIndex(final T chars, final int index, final String message, final Object... values) {
- notNull(chars);
- if (index < 0 || index >= chars.length()) {
- throw new IndexOutOfBoundsException(String.format(message, values));
- }
- return chars;
- }
-
- /**
- * Validates that the index is within the bounds of the argument
- * character sequence; otherwise throwing an exception.
- *
- * Validate.validIndex(myStr, 2);
- *
- * If the character sequence is {@code null}, then the message
- * of the exception is "The validated object is
- * null".
- *
- * If the index is invalid, then the message of the exception
- * is "The validated character sequence index is invalid: "
- * followed by the index.
- *
- * @param the character sequence type
- * @param chars the character sequence to check, validated not null by this method
- * @param index the index to check
- * @return the validated character sequence (never {@code null} for method chaining)
- * @throws NullPointerException if the character sequence is {@code null}
- * @throws IndexOutOfBoundsException if the index is invalid
- * @see #validIndex(CharSequence, int, String, Object...)
- *
- * @since 3.0
- */
- public static T validIndex(final T chars, final int index) {
- return validIndex(chars, index, DEFAULT_VALID_INDEX_CHAR_SEQUENCE_EX_MESSAGE, Integer.valueOf(index));
- }
-
- // validState
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the stateful condition is {@code true}; otherwise
- * throwing an exception. This method is useful when validating according
- * to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- *
- * Validate.validState(field > 0);
- * Validate.validState(this.isOk());
- *
- * The message of the exception is "The validated state is
- * false".
- *
- * @param expression the boolean expression to check
- * @throws IllegalStateException if expression is {@code false}
- * @see #validState(boolean, String, Object...)
- *
- * @since 3.0
- */
- public static void validState(final boolean expression) {
- if (!expression) {
- throw new IllegalStateException(DEFAULT_VALID_STATE_EX_MESSAGE);
- }
- }
-
- /**
- * Validate that the stateful condition is {@code true}; otherwise
- * throwing an exception with the specified message. This method is useful when
- * validating according to an arbitrary boolean expression, such as validating a
- * primitive number or using your own custom validation expression.
- *
- * Validate.validState(this.isOk(), "The state is not OK: %s", myObject);
- *
- * @param expression the boolean expression to check
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalStateException if expression is {@code false}
- * @see #validState(boolean)
- *
- * @since 3.0
- */
- public static void validState(final boolean expression, final String message, final Object... values) {
- if (!expression) {
- throw new IllegalStateException(String.format(message, values));
- }
- }
-
- // matchesPattern
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument character sequence matches the specified regular
- * expression pattern; otherwise throwing an exception.
- *
- * Validate.matchesPattern("hi", "[a-z]*");
- *
- * The syntax of the pattern is the one used in the {@link Pattern} class.
- *
- * @param input the character sequence to validate, not null
- * @param pattern the regular expression pattern, not null
- * @throws IllegalArgumentException if the character sequence does not match the pattern
- * @see #matchesPattern(CharSequence, String, String, Object...)
- *
- * @since 3.0
- */
- public static void matchesPattern(final CharSequence input, final String pattern) {
- // TODO when breaking BC, consider returning input
- if (!Pattern.matches(pattern, input)) {
- throw new IllegalArgumentException(String.format(DEFAULT_MATCHES_PATTERN_EX, input, pattern));
- }
- }
-
- /**
- * Validate that the specified argument character sequence matches the specified regular
- * expression pattern; otherwise throwing an exception with the specified message.
- *
- * Validate.matchesPattern("hi", "[a-z]*", "%s does not match %s", "hi" "[a-z]*");
- *
- * The syntax of the pattern is the one used in the {@link Pattern} class.
- *
- * @param input the character sequence to validate, not null
- * @param pattern the regular expression pattern, not null
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if the character sequence does not match the pattern
- * @see #matchesPattern(CharSequence, String)
- *
- * @since 3.0
- */
- public static void matchesPattern(final CharSequence input, final String pattern, final String message, final Object... values) {
- // TODO when breaking BC, consider returning input
- if (!Pattern.matches(pattern, input)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- // notNaN
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the specified argument is not {@code NaN}; otherwise
- * throwing an exception.
- *
- * Validate.notNaN(myDouble);
- *
- * The message of the exception is "The validated value is not a
- * number".
- *
- * @param value the value to validate
- * @throws IllegalArgumentException if the value is not a number
- * @see #notNaN(double, String, Object...)
- *
- * @since 3.5
- */
- public static void notNaN(final double value) {
- notNaN(value, DEFAULT_NOT_NAN_EX_MESSAGE);
- }
-
- /**
- * Validates that the specified argument is not {@code NaN}; otherwise
- * throwing an exception with the specified message.
- *
- * Validate.notNaN(myDouble, "The value must be a number");
- *
- * @param value the value to validate
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message
- * @throws IllegalArgumentException if the value is not a number
- * @see #notNaN(double)
- *
- * @since 3.5
- */
- public static void notNaN(final double value, final String message, final Object... values) {
- if (Double.isNaN(value)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- // finite
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the specified argument is not infinite or {@code NaN};
- * otherwise throwing an exception.
- *
- * Validate.finite(myDouble);
- *
- * The message of the exception is "The value is invalid: %f".
- *
- * @param value the value to validate
- * @throws IllegalArgumentException if the value is infinite or {@code NaN}
- * @see #finite(double, String, Object...)
- *
- * @since 3.5
- */
- public static void finite(final double value) {
- finite(value, DEFAULT_FINITE_EX_MESSAGE, value);
- }
-
- /**
- * Validates that the specified argument is not infinite or {@code NaN};
- * otherwise throwing an exception with the specified message.
- *
- * Validate.finite(myDouble, "The argument must contain a numeric value");
- *
- * @param value the value to validate
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message
- * @throws IllegalArgumentException if the value is infinite or {@code NaN}
- * @see #finite(double)
- *
- * @since 3.5
- */
- public static void finite(final double value, final String message, final Object... values) {
- if (Double.isNaN(value) || Double.isInfinite(value)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- // inclusiveBetween
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument object fall between the two
- * inclusive values specified; otherwise, throws an exception.
- *
- * Validate.inclusiveBetween(0, 2, 1);
- *
- * @param the type of the argument object
- * @param start the inclusive start value, not null
- * @param end the inclusive end value, not null
- * @param value the object to validate, not null
- * @throws IllegalArgumentException if the value falls outside the boundaries
- * @see #inclusiveBetween(Object, Object, Comparable, String, Object...)
- *
- * @since 3.0
- */
- public static void inclusiveBetween(final T start, final T end, final Comparable value) {
- // TODO when breaking BC, consider returning value
- if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {
- throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified argument object fall between the two
- * inclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.inclusiveBetween(0, 2, 1, "Not in boundaries");
- *
- * @param the type of the argument object
- * @param start the inclusive start value, not null
- * @param end the inclusive end value, not null
- * @param value the object to validate, not null
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if the value falls outside the boundaries
- * @see #inclusiveBetween(Object, Object, Comparable)
- *
- * @since 3.0
- */
- public static void inclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) {
- // TODO when breaking BC, consider returning value
- if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * inclusive values specified; otherwise, throws an exception.
- *
- * Validate.inclusiveBetween(0, 2, 1);
- *
- * @param start the inclusive start value
- * @param end the inclusive end value
- * @param value the value to validate
- * @throws IllegalArgumentException if the value falls outside the boundaries (inclusive)
- *
- * @since 3.3
- */
- @SuppressWarnings("boxing")
- public static void inclusiveBetween(final long start, final long end, final long value) {
- // TODO when breaking BC, consider returning value
- if (value < start || value > end) {
- throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * inclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.inclusiveBetween(0, 2, 1, "Not in range");
- *
- * @param start the inclusive start value
- * @param end the inclusive end value
- * @param value the value to validate
- * @param message the exception message if invalid, not null
- *
- * @throws IllegalArgumentException if the value falls outside the boundaries
- *
- * @since 3.3
- */
- public static void inclusiveBetween(final long start, final long end, final long value, final String message) {
- // TODO when breaking BC, consider returning value
- if (value < start || value > end) {
- throw new IllegalArgumentException(message);
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * inclusive values specified; otherwise, throws an exception.
- *
- * Validate.inclusiveBetween(0.1, 2.1, 1.1);
- *
- * @param start the inclusive start value
- * @param end the inclusive end value
- * @param value the value to validate
- * @throws IllegalArgumentException if the value falls outside the boundaries (inclusive)
- *
- * @since 3.3
- */
- @SuppressWarnings("boxing")
- public static void inclusiveBetween(final double start, final double end, final double value) {
- // TODO when breaking BC, consider returning value
- if (value < start || value > end) {
- throw new IllegalArgumentException(String.format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * inclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.inclusiveBetween(0.1, 2.1, 1.1, "Not in range");
- *
- * @param start the inclusive start value
- * @param end the inclusive end value
- * @param value the value to validate
- * @param message the exception message if invalid, not null
- *
- * @throws IllegalArgumentException if the value falls outside the boundaries
- *
- * @since 3.3
- */
- public static void inclusiveBetween(final double start, final double end, final double value, final String message) {
- // TODO when breaking BC, consider returning value
- if (value < start || value > end) {
- throw new IllegalArgumentException(message);
- }
- }
-
- // exclusiveBetween
- //---------------------------------------------------------------------------------
-
- /**
- * Validate that the specified argument object fall between the two
- * exclusive values specified; otherwise, throws an exception.
- *
- * Validate.exclusiveBetween(0, 2, 1);
- *
- * @param the type of the argument object
- * @param start the exclusive start value, not null
- * @param end the exclusive end value, not null
- * @param value the object to validate, not null
- * @throws IllegalArgumentException if the value falls outside the boundaries
- * @see #exclusiveBetween(Object, Object, Comparable, String, Object...)
- *
- * @since 3.0
- */
- public static void exclusiveBetween(final T start, final T end, final Comparable value) {
- // TODO when breaking BC, consider returning value
- if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {
- throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified argument object fall between the two
- * exclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.exclusiveBetween(0, 2, 1, "Not in boundaries");
- *
- * @param the type of the argument object
- * @param start the exclusive start value, not null
- * @param end the exclusive end value, not null
- * @param value the object to validate, not null
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if the value falls outside the boundaries
- * @see #exclusiveBetween(Object, Object, Comparable)
- *
- * @since 3.0
- */
- public static void exclusiveBetween(final T start, final T end, final Comparable value, final String message, final Object... values) {
- // TODO when breaking BC, consider returning value
- if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * exclusive values specified; otherwise, throws an exception.
- *
- * Validate.exclusiveBetween(0, 2, 1);
- *
- * @param start the exclusive start value
- * @param end the exclusive end value
- * @param value the value to validate
- * @throws IllegalArgumentException if the value falls out of the boundaries
- *
- * @since 3.3
- */
- @SuppressWarnings("boxing")
- public static void exclusiveBetween(final long start, final long end, final long value) {
- // TODO when breaking BC, consider returning value
- if (value <= start || value >= end) {
- throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * exclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.exclusiveBetween(0, 2, 1, "Not in range");
- *
- * @param start the exclusive start value
- * @param end the exclusive end value
- * @param value the value to validate
- * @param message the exception message if invalid, not null
- *
- * @throws IllegalArgumentException if the value falls outside the boundaries
- *
- * @since 3.3
- */
- public static void exclusiveBetween(final long start, final long end, final long value, final String message) {
- // TODO when breaking BC, consider returning value
- if (value <= start || value >= end) {
- throw new IllegalArgumentException(message);
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * exclusive values specified; otherwise, throws an exception.
- *
- * Validate.exclusiveBetween(0.1, 2.1, 1.1);
- *
- * @param start the exclusive start value
- * @param end the exclusive end value
- * @param value the value to validate
- * @throws IllegalArgumentException if the value falls out of the boundaries
- *
- * @since 3.3
- */
- @SuppressWarnings("boxing")
- public static void exclusiveBetween(final double start, final double end, final double value) {
- // TODO when breaking BC, consider returning value
- if (value <= start || value >= end) {
- throw new IllegalArgumentException(String.format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
- }
- }
-
- /**
- * Validate that the specified primitive value falls between the two
- * exclusive values specified; otherwise, throws an exception with the
- * specified message.
- *
- * Validate.exclusiveBetween(0.1, 2.1, 1.1, "Not in range");
- *
- * @param start the exclusive start value
- * @param end the exclusive end value
- * @param value the value to validate
- * @param message the exception message if invalid, not null
- *
- * @throws IllegalArgumentException if the value falls outside the boundaries
- *
- * @since 3.3
- */
- public static void exclusiveBetween(final double start, final double end, final double value, final String message) {
- // TODO when breaking BC, consider returning value
- if (value <= start || value >= end) {
- throw new IllegalArgumentException(message);
- }
- }
-
- // isInstanceOf
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the argument is an instance of the specified class, if not throws an exception.
- *
- * This method is useful when validating according to an arbitrary class
- *
- * Validate.isInstanceOf(OkClass.class, object);
- *
- * The message of the exception is "Expected type: {type}, actual: {obj_type}"
- *
- * @param type the class the object must be validated against, not null
- * @param obj the object to check, null throws an exception
- * @throws IllegalArgumentException if argument is not of specified class
- * @see #isInstanceOf(Class, Object, String, Object...)
- *
- * @since 3.0
- */
- public static void isInstanceOf(final Class> type, final Object obj) {
- // TODO when breaking BC, consider returning obj
- if (!type.isInstance(obj)) {
- throw new IllegalArgumentException(String.format(DEFAULT_IS_INSTANCE_OF_EX_MESSAGE, type.getName(),
- obj == null ? "null" : obj.getClass().getName()));
- }
- }
-
- /**
- * Validate that the argument is an instance of the specified class; otherwise
- * throwing an exception with the specified message. This method is useful when
- * validating according to an arbitrary class
- *
- * Validate.isInstanceOf(OkClass.class, object, "Wrong class, object is of class %s",
- * object.getClass().getName());
- *
- * @param type the class the object must be validated against, not null
- * @param obj the object to check, null throws an exception
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if argument is not of specified class
- * @see #isInstanceOf(Class, Object)
- *
- * @since 3.0
- */
- public static void isInstanceOf(final Class> type, final Object obj, final String message, final Object... values) {
- // TODO when breaking BC, consider returning obj
- if (!type.isInstance(obj)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-
- // isAssignableFrom
- //---------------------------------------------------------------------------------
-
- /**
- * Validates that the argument can be converted to the specified class, if not, throws an exception.
- *
- * This method is useful when validating that there will be no casting errors.
- *
- * Validate.isAssignableFrom(SuperClass.class, object.getClass());
- *
- * The message format of the exception is "Cannot assign {type} to {superType}"
- *
- * @param superType the class the class must be validated against, not null
- * @param type the class to check, not null
- * @throws IllegalArgumentException if type argument is not assignable to the specified superType
- * @see #isAssignableFrom(Class, Class, String, Object...)
- *
- * @since 3.0
- */
- public static void isAssignableFrom(final Class> superType, final Class> type) {
- // TODO when breaking BC, consider returning type
- if (!superType.isAssignableFrom(type)) {
- throw new IllegalArgumentException(String.format(DEFAULT_IS_ASSIGNABLE_EX_MESSAGE, type == null ? "null" : type.getName(),
- superType.getName()));
- }
- }
-
- /**
- * Validates that the argument can be converted to the specified class, if not throws an exception.
- *
- * This method is useful when validating if there will be no casting errors.
- *
- * Validate.isAssignableFrom(SuperClass.class, object.getClass());
- *
- * The message of the exception is "The validated object can not be converted to the"
- * followed by the name of the class and "class"
- *
- * @param superType the class the class must be validated against, not null
- * @param type the class to check, not null
- * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
- * @param values the optional values for the formatted exception message, null array not recommended
- * @throws IllegalArgumentException if argument can not be converted to the specified class
- * @see #isAssignableFrom(Class, Class)
- */
- public static void isAssignableFrom(final Class> superType, final Class> type, final String message, final Object... values) {
- // TODO when breaking BC, consider returning type
- if (!superType.isAssignableFrom(type)) {
- throw new IllegalArgumentException(String.format(message, values));
- }
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/AggregateTranslator.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/AggregateTranslator.java
deleted file mode 100644
index 9eb58609..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/AggregateTranslator.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Executes a sequence of translators one after the other. Execution ends whenever
- * the first translator consumes codepoints from the input.
- *
- * @since 1.0
- */
-public class AggregateTranslator extends CharSequenceTranslator {
-
- /**
- * Translator list.
- */
- private final List translators = new ArrayList<>();
-
- /**
- * Specify the translators to be used at creation time.
- *
- * @param translators CharSequenceTranslator array to aggregate
- */
- public AggregateTranslator(final CharSequenceTranslator... translators) {
- if (translators != null) {
- for (final CharSequenceTranslator translator : translators) {
- if (translator != null) {
- this.translators.add(translator);
- }
- }
- }
- }
-
- /**
- * The first translator to consume codepoints from the input is the 'winner'.
- * Execution stops with the number of consumed codepoints being returned.
- * {@inheritDoc}
- */
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- for (final CharSequenceTranslator translator : translators) {
- final int consumed = translator.translate(input, index, out);
- if (consumed != 0) {
- return consumed;
- }
- }
- return 0;
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CharSequenceTranslator.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CharSequenceTranslator.java
deleted file mode 100644
index 3257abd1..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CharSequenceTranslator.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-
-import com.joyy.stringescape.Validate;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Locale;
-
-/**
- * An API for translating text.
- * Its core use is to escape and unescape text. Because escaping and unescaping
- * is completely contextual, the API does not present two separate signatures.
- *
- * @since 1.0
- */
-public abstract class CharSequenceTranslator {
-
- /**
- * Array containing the hexadecimal alphabet.
- */
- static final char[] HEX_DIGITS = new char[] {'0', '1', '2', '3',
- '4', '5', '6', '7',
- '8', '9', 'A', 'B',
- 'C', 'D', 'E', 'F'};
-
- /**
- * Translate a set of codepoints, represented by an int index into a CharSequence,
- * into another set of codepoints. The number of codepoints consumed must be returned,
- * and the only IOExceptions thrown must be from interacting with the Writer so that
- * the top level API may reliably ignore StringWriter IOExceptions.
- *
- * @param input CharSequence that is being translated
- * @param index int representing the current point of translation
- * @param out Writer to translate the text to
- * @return int count of codepoints consumed
- * @throws IOException if and only if the Writer produces an IOException
- */
- public abstract int translate(CharSequence input, int index, Writer out) throws IOException;
-
- /**
- * Helper for non-Writer usage.
- * @param input CharSequence to be translated
- * @return String output of translation
- */
- public final String translate(final CharSequence input) {
- if (input == null) {
- return null;
- }
- try {
- final StringWriter writer = new StringWriter(input.length() * 2);
- translate(input, writer);
- return writer.toString();
- } catch (final IOException ioe) {
- // this should never ever happen while writing to a StringWriter
- throw new RuntimeException(ioe);
- }
- }
-
- /**
- * Translate an input onto a Writer. This is intentionally final as its algorithm is
- * tightly coupled with the abstract method of this class.
- *
- * @param input CharSequence that is being translated
- * @param out Writer to translate the text to
- * @throws IOException if and only if the Writer produces an IOException
- */
- public final void translate(final CharSequence input, final Writer out) throws IOException {
- Validate.isTrue(out != null, "The Writer must not be null");
- if (input == null) {
- return;
- }
- int pos = 0;
- final int len = input.length();
- while (pos < len) {
- final int consumed = translate(input, pos, out);
- if (consumed == 0) {
- // inlined implementation of Character.toChars(Character.codePointAt(input, pos))
- // avoids allocating temp char arrays and duplicate checks
- final char c1 = input.charAt(pos);
- out.write(c1);
- pos++;
- if (Character.isHighSurrogate(c1) && pos < len) {
- final char c2 = input.charAt(pos);
- if (Character.isLowSurrogate(c2)) {
- out.write(c2);
- pos++;
- }
- }
- continue;
- }
- // contract with translators is that they have to understand codepoints
- // and they just took care of a surrogate pair
- for (int pt = 0; pt < consumed; pt++) {
- pos += Character.charCount(Character.codePointAt(input, pos));
- }
- }
- }
-
- /**
- * Helper method to create a merger of this translator with another set of
- * translators. Useful in customizing the standard functionality.
- *
- * @param translators CharSequenceTranslator array of translators to merge with this one
- * @return CharSequenceTranslator merging this translator with the others
- */
- public final CharSequenceTranslator with(final CharSequenceTranslator... translators) {
- final CharSequenceTranslator[] newArray = new CharSequenceTranslator[translators.length + 1];
- newArray[0] = this;
- System.arraycopy(translators, 0, newArray, 1, translators.length);
- return new AggregateTranslator(newArray);
- }
-
- /**
- * Returns an upper case hexadecimal String for the given
- * character.
- *
- * @param codepoint The codepoint to convert.
- * @return An upper case hexadecimal String
- */
- public static String hex(final int codepoint) {
- return Integer.toHexString(codepoint).toUpperCase(Locale.ENGLISH);
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CodePointTranslator.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CodePointTranslator.java
deleted file mode 100644
index 63bd040d..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CodePointTranslator.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Helper subclass to CharSequenceTranslator to allow for translations that
- * will replace up to one character at a time.
- *
- * @since 1.0
- */
-public abstract class CodePointTranslator extends CharSequenceTranslator {
-
- /**
- * Implementation of translate that maps onto the abstract translate(int, Writer) method.
- * {@inheritDoc}
- */
- @Override
- public final int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- final int codepoint = Character.codePointAt(input, index);
- final boolean consumed = translate(codepoint, out);
- return consumed ? 1 : 0;
- }
-
- /**
- * Translate the specified codepoint into another.
- *
- * @param codepoint int character input to translate
- * @param out Writer to optionally push the translated output to
- * @return boolean as to whether translation occurred or not
- * @throws IOException if and only if the Writer produces an IOException
- */
- public abstract boolean translate(int codepoint, Writer out) throws IOException;
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CsvTranslators.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CsvTranslators.java
deleted file mode 100644
index 4b2f63c6..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/CsvTranslators.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-
-import com.joyy.stringescape.CharUtils;
-import com.joyy.stringescape.StringUtils;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * This class holds inner classes for escaping/unescaping Comma Separated Values.
- *
- * In general the use a high level API like Apache Commons
- * CSV should be preferred over these low level classes.
- *
- *
- * @see Apache Commons CSV
- */
-public final class CsvTranslators {
-
- /** Comma character. */
- private static final char CSV_DELIMITER = ',';
- /** Quote character. */
- private static final char CSV_QUOTE = '"';
- /** Quote character converted to string. */
- private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
- /** Escaped quote string. */
- private static final String CSV_ESCAPED_QUOTE_STR = CSV_QUOTE_STR + CSV_QUOTE_STR;
- /** CSV key characters in an array. */
- private static final char[] CSV_SEARCH_CHARS =
- new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
-
- /** Hidden constructor. */
- private CsvTranslators() { }
-
- /**
- * Translator for escaping Comma Separated Values.
- */
- public static class CsvEscaper extends SinglePassTranslator {
-
- @Override
- void translateWhole(final CharSequence input, final Writer out) throws IOException {
- final String inputSting = input.toString();
- if (StringUtils.containsNone(inputSting, CSV_SEARCH_CHARS)) {
- out.write(inputSting);
- } else {
- // input needs quoting
- out.write(CSV_QUOTE);
- out.write(StringUtils.replace(inputSting, CSV_QUOTE_STR, CSV_ESCAPED_QUOTE_STR));
- out.write(CSV_QUOTE);
- }
- }
- }
-
- /**
- * Translator for unescaping escaped Comma Separated Value entries.
- */
- public static class CsvUnescaper extends SinglePassTranslator {
-
- @Override
- void translateWhole(final CharSequence input, final Writer out) throws IOException {
- // is input not quoted?
- if (input.charAt(0) != CSV_QUOTE || input.charAt(input.length() - 1) != CSV_QUOTE) {
- out.write(input.toString());
- return;
- }
-
- // strip quotes
- final String quoteless = input.subSequence(1, input.length() - 1).toString();
-
- if (StringUtils.containsAny(quoteless, CSV_SEARCH_CHARS)) {
- // deal with escaped quotes; ie) ""
- out.write(StringUtils.replace(quoteless, CSV_ESCAPED_QUOTE_STR, CSV_QUOTE_STR));
- } else {
- out.write(input.toString());
- }
- }
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/EntityArrays.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/EntityArrays.java
deleted file mode 100644
index 72ef690b..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/EntityArrays.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class holding various entity data for HTML and XML - generally for use with
- * the LookupTranslator.
- * All Maps are generated using java.util.Collections.unmodifiableMap().
- *
- * @since 1.0
- */
-public class EntityArrays {
-
- /**
- * A Map<CharSequence, CharSequence> to to escape
- * ISO-8859-1
- * characters to their named HTML 3.x equivalents.
- */
- public static final Map ISO8859_1_ESCAPE;
- static {
- final Map initialMap = new HashMap<>();
- initialMap.put("\u00A0", " "); // non-breaking space
- initialMap.put("\u00A1", "¡"); // inverted exclamation mark
- initialMap.put("\u00A2", "¢"); // cent sign
- initialMap.put("\u00A3", "£"); // pound sign
- initialMap.put("\u00A4", "¤"); // currency sign
- initialMap.put("\u00A5", "¥"); // yen sign = yuan sign
- initialMap.put("\u00A6", "¦"); // broken bar = broken vertical bar
- initialMap.put("\u00A7", "§"); // section sign
- initialMap.put("\u00A8", "¨"); // diaeresis = spacing diaeresis
- initialMap.put("\u00A9", "©"); // © - copyright sign
- initialMap.put("\u00AA", "ª"); // feminine ordinal indicator
- initialMap.put("\u00AB", "«"); // left-pointing double angle quotation mark = left pointing guillemet
- initialMap.put("\u00AC", "¬"); // not sign
- initialMap.put("\u00AD", ""); // soft hyphen = discretionary hyphen
- initialMap.put("\u00AE", "®"); // ® - registered trademark sign
- initialMap.put("\u00AF", "¯"); // macron = spacing macron = overline = APL overbar
- initialMap.put("\u00B0", "°"); // degree sign
- initialMap.put("\u00B1", "±"); // plus-minus sign = plus-or-minus sign
- initialMap.put("\u00B2", "²"); // superscript two = superscript digit two = squared
- initialMap.put("\u00B3", "³"); // superscript three = superscript digit three = cubed
- initialMap.put("\u00B4", "´"); // acute accent = spacing acute
- initialMap.put("\u00B5", "µ"); // micro sign
- initialMap.put("\u00B6", "¶"); // pilcrow sign = paragraph sign
- initialMap.put("\u00B7", "·"); // middle dot = Georgian comma = Greek middle dot
- initialMap.put("\u00B8", "¸"); // cedilla = spacing cedilla
- initialMap.put("\u00B9", "¹"); // superscript one = superscript digit one
- initialMap.put("\u00BA", "º"); // masculine ordinal indicator
- initialMap.put("\u00BB", "»"); // right-pointing double angle quotation mark = right pointing guillemet
- initialMap.put("\u00BC", "¼"); // vulgar fraction one quarter = fraction one quarter
- initialMap.put("\u00BD", "½"); // vulgar fraction one half = fraction one half
- initialMap.put("\u00BE", "¾"); // vulgar fraction three quarters = fraction three quarters
- initialMap.put("\u00BF", "¿"); // inverted question mark = turned question mark
- initialMap.put("\u00C0", "À"); // À - uppercase A, grave accent
- initialMap.put("\u00C1", "Á"); // Á - uppercase A, acute accent
- initialMap.put("\u00C2", "Â"); // Â - uppercase A, circumflex accent
- initialMap.put("\u00C3", "Ã"); // Ã - uppercase A, tilde
- initialMap.put("\u00C4", "Ä"); // Ä - uppercase A, umlaut
- initialMap.put("\u00C5", "Å"); // Å - uppercase A, ring
- initialMap.put("\u00C6", "Æ"); // Æ - uppercase AE
- initialMap.put("\u00C7", "Ç"); // Ç - uppercase C, cedilla
- initialMap.put("\u00C8", "È"); // È - uppercase E, grave accent
- initialMap.put("\u00C9", "É"); // É - uppercase E, acute accent
- initialMap.put("\u00CA", "Ê"); // Ê - uppercase E, circumflex accent
- initialMap.put("\u00CB", "Ë"); // Ë - uppercase E, umlaut
- initialMap.put("\u00CC", "Ì"); // Ì - uppercase I, grave accent
- initialMap.put("\u00CD", "Í"); // Í - uppercase I, acute accent
- initialMap.put("\u00CE", "Î"); // Î - uppercase I, circumflex accent
- initialMap.put("\u00CF", "Ï"); // Ï - uppercase I, umlaut
- initialMap.put("\u00D0", "Ð"); // Ð - uppercase Eth, Icelandic
- initialMap.put("\u00D1", "Ñ"); // Ñ - uppercase N, tilde
- initialMap.put("\u00D2", "Ò"); // Ò - uppercase O, grave accent
- initialMap.put("\u00D3", "Ó"); // Ó - uppercase O, acute accent
- initialMap.put("\u00D4", "Ô"); // Ô - uppercase O, circumflex accent
- initialMap.put("\u00D5", "Õ"); // Õ - uppercase O, tilde
- initialMap.put("\u00D6", "Ö"); // Ö - uppercase O, umlaut
- initialMap.put("\u00D7", "×"); // multiplication sign
- initialMap.put("\u00D8", "Ø"); // Ø - uppercase O, slash
- initialMap.put("\u00D9", "Ù"); // Ù - uppercase U, grave accent
- initialMap.put("\u00DA", "Ú"); // Ú - uppercase U, acute accent
- initialMap.put("\u00DB", "Û"); // Û - uppercase U, circumflex accent
- initialMap.put("\u00DC", "Ü"); // Ü - uppercase U, umlaut
- initialMap.put("\u00DD", "Ý"); // Ý - uppercase Y, acute accent
- initialMap.put("\u00DE", "Þ"); // Þ - uppercase THORN, Icelandic
- initialMap.put("\u00DF", "ß"); // ß - lowercase sharps, German
- initialMap.put("\u00E0", "à"); // à - lowercase a, grave accent
- initialMap.put("\u00E1", "á"); // á - lowercase a, acute accent
- initialMap.put("\u00E2", "â"); // â - lowercase a, circumflex accent
- initialMap.put("\u00E3", "ã"); // ã - lowercase a, tilde
- initialMap.put("\u00E4", "ä"); // ä - lowercase a, umlaut
- initialMap.put("\u00E5", "å"); // å - lowercase a, ring
- initialMap.put("\u00E6", "æ"); // æ - lowercase ae
- initialMap.put("\u00E7", "ç"); // ç - lowercase c, cedilla
- initialMap.put("\u00E8", "è"); // è - lowercase e, grave accent
- initialMap.put("\u00E9", "é"); // é - lowercase e, acute accent
- initialMap.put("\u00EA", "ê"); // ê - lowercase e, circumflex accent
- initialMap.put("\u00EB", "ë"); // ë - lowercase e, umlaut
- initialMap.put("\u00EC", "ì"); // ì - lowercase i, grave accent
- initialMap.put("\u00ED", "í"); // í - lowercase i, acute accent
- initialMap.put("\u00EE", "î"); // î - lowercase i, circumflex accent
- initialMap.put("\u00EF", "ï"); // ï - lowercase i, umlaut
- initialMap.put("\u00F0", "ð"); // ð - lowercase eth, Icelandic
- initialMap.put("\u00F1", "ñ"); // ñ - lowercase n, tilde
- initialMap.put("\u00F2", "ò"); // ò - lowercase o, grave accent
- initialMap.put("\u00F3", "ó"); // ó - lowercase o, acute accent
- initialMap.put("\u00F4", "ô"); // ô - lowercase o, circumflex accent
- initialMap.put("\u00F5", "õ"); // õ - lowercase o, tilde
- initialMap.put("\u00F6", "ö"); // ö - lowercase o, umlaut
- initialMap.put("\u00F7", "÷"); // division sign
- initialMap.put("\u00F8", "ø"); // ø - lowercase o, slash
- initialMap.put("\u00F9", "ù"); // ù - lowercase u, grave accent
- initialMap.put("\u00FA", "ú"); // ú - lowercase u, acute accent
- initialMap.put("\u00FB", "û"); // û - lowercase u, circumflex accent
- initialMap.put("\u00FC", "ü"); // ü - lowercase u, umlaut
- initialMap.put("\u00FD", "ý"); // ý - lowercase y, acute accent
- initialMap.put("\u00FE", "þ"); // þ - lowercase thorn, Icelandic
- initialMap.put("\u00FF", "ÿ"); // ÿ - lowercase y, umlaut
- ISO8859_1_ESCAPE = Collections.unmodifiableMap(initialMap);
- }
-
- /**
- * Reverse of {@link #ISO8859_1_ESCAPE} for unescaping purposes.
- */
- public static final Map ISO8859_1_UNESCAPE;
- static {
- ISO8859_1_UNESCAPE = Collections.unmodifiableMap(invert(ISO8859_1_ESCAPE));
- }
-
- /**
- * A Map<CharSequence, CharSequence> to escape additional
- * character entity
- * references . Note that this must be used with {@link #ISO8859_1_ESCAPE} to get the full list of
- * HTML 4.0 character entities.
- */
- public static final Map HTML40_EXTENDED_ESCAPE;
- static {
- final Map initialMap = new HashMap<>();
- //
- initialMap.put("\u0192", "ƒ"); // latin small f with hook = function= florin, U+0192 ISOtech -->
- //
- initialMap.put("\u0391", "Α"); // greek capital letter alpha, U+0391 -->
- initialMap.put("\u0392", "Β"); // greek capital letter beta, U+0392 -->
- initialMap.put("\u0393", "Γ"); // greek capital letter gamma,U+0393 ISOgrk3 -->
- initialMap.put("\u0394", "Δ"); // greek capital letter delta,U+0394 ISOgrk3 -->
- initialMap.put("\u0395", "Ε"); // greek capital letter epsilon, U+0395 -->
- initialMap.put("\u0396", "Ζ"); // greek capital letter zeta, U+0396 -->
- initialMap.put("\u0397", "Η"); // greek capital letter eta, U+0397 -->
- initialMap.put("\u0398", "Θ"); // greek capital letter theta,U+0398 ISOgrk3 -->
- initialMap.put("\u0399", "Ι"); // greek capital letter iota, U+0399 -->
- initialMap.put("\u039A", "Κ"); // greek capital letter kappa, U+039A -->
- initialMap.put("\u039B", "Λ"); // greek capital letter lambda,U+039B ISOgrk3 -->
- initialMap.put("\u039C", "Μ"); // greek capital letter mu, U+039C -->
- initialMap.put("\u039D", "Ν"); // greek capital letter nu, U+039D -->
- initialMap.put("\u039E", "Ξ"); // greek capital letter xi, U+039E ISOgrk3 -->
- initialMap.put("\u039F", "Ο"); // greek capital letter omicron, U+039F -->
- initialMap.put("\u03A0", "Π"); // greek capital letter pi, U+03A0 ISOgrk3 -->
- initialMap.put("\u03A1", "Ρ"); // greek capital letter rho, U+03A1 -->
- //
- initialMap.put("\u03A3", "Σ"); // greek capital letter sigma,U+03A3 ISOgrk3 -->
- initialMap.put("\u03A4", "Τ"); // greek capital letter tau, U+03A4 -->
- initialMap.put("\u03A5", "Υ"); // greek capital letter upsilon,U+03A5 ISOgrk3 -->
- initialMap.put("\u03A6", "Φ"); // greek capital letter phi,U+03A6 ISOgrk3 -->
- initialMap.put("\u03A7", "Χ"); // greek capital letter chi, U+03A7 -->
- initialMap.put("\u03A8", "Ψ"); // greek capital letter psi,U+03A8 ISOgrk3 -->
- initialMap.put("\u03A9", "Ω"); // greek capital letter omega,U+03A9 ISOgrk3 -->
- initialMap.put("\u03B1", "α"); // greek small letter alpha,U+03B1 ISOgrk3 -->
- initialMap.put("\u03B2", "β"); // greek small letter beta, U+03B2 ISOgrk3 -->
- initialMap.put("\u03B3", "γ"); // greek small letter gamma,U+03B3 ISOgrk3 -->
- initialMap.put("\u03B4", "δ"); // greek small letter delta,U+03B4 ISOgrk3 -->
- initialMap.put("\u03B5", "ε"); // greek small letter epsilon,U+03B5 ISOgrk3 -->
- initialMap.put("\u03B6", "ζ"); // greek small letter zeta, U+03B6 ISOgrk3 -->
- initialMap.put("\u03B7", "η"); // greek small letter eta, U+03B7 ISOgrk3 -->
- initialMap.put("\u03B8", "θ"); // greek small letter theta,U+03B8 ISOgrk3 -->
- initialMap.put("\u03B9", "ι"); // greek small letter iota, U+03B9 ISOgrk3 -->
- initialMap.put("\u03BA", "κ"); // greek small letter kappa,U+03BA ISOgrk3 -->
- initialMap.put("\u03BB", "λ"); // greek small letter lambda,U+03BB ISOgrk3 -->
- initialMap.put("\u03BC", "μ"); // greek small letter mu, U+03BC ISOgrk3 -->
- initialMap.put("\u03BD", "ν"); // greek small letter nu, U+03BD ISOgrk3 -->
- initialMap.put("\u03BE", "ξ"); // greek small letter xi, U+03BE ISOgrk3 -->
- initialMap.put("\u03BF", "ο"); // greek small letter omicron, U+03BF NEW -->
- initialMap.put("\u03C0", "π"); // greek small letter pi, U+03C0 ISOgrk3 -->
- initialMap.put("\u03C1", "ρ"); // greek small letter rho, U+03C1 ISOgrk3 -->
- initialMap.put("\u03C2", "ς"); // greek small letter final sigma,U+03C2 ISOgrk3 -->
- initialMap.put("\u03C3", "σ"); // greek small letter sigma,U+03C3 ISOgrk3 -->
- initialMap.put("\u03C4", "τ"); // greek small letter tau, U+03C4 ISOgrk3 -->
- initialMap.put("\u03C5", "υ"); // greek small letter upsilon,U+03C5 ISOgrk3 -->
- initialMap.put("\u03C6", "φ"); // greek small letter phi, U+03C6 ISOgrk3 -->
- initialMap.put("\u03C7", "χ"); // greek small letter chi, U+03C7 ISOgrk3 -->
- initialMap.put("\u03C8", "ψ"); // greek small letter psi, U+03C8 ISOgrk3 -->
- initialMap.put("\u03C9", "ω"); // greek small letter omega,U+03C9 ISOgrk3 -->
- initialMap.put("\u03D1", "ϑ"); // greek small letter theta symbol,U+03D1 NEW -->
- initialMap.put("\u03D2", "ϒ"); // greek upsilon with hook symbol,U+03D2 NEW -->
- initialMap.put("\u03D6", "ϖ"); // greek pi symbol, U+03D6 ISOgrk3 -->
- //
- initialMap.put("\u2022", "•"); // bullet = black small circle,U+2022 ISOpub -->
- //
- initialMap.put("\u2026", "…"); // horizontal ellipsis = three dot leader,U+2026 ISOpub -->
- initialMap.put("\u2032", "′"); // prime = minutes = feet, U+2032 ISOtech -->
- initialMap.put("\u2033", "″"); // double prime = seconds = inches,U+2033 ISOtech -->
- initialMap.put("\u203E", "‾"); // overline = spacing overscore,U+203E NEW -->
- initialMap.put("\u2044", "⁄"); // fraction slash, U+2044 NEW -->
- //
- initialMap.put("\u2118", "℘"); // script capital P = power set= Weierstrass p, U+2118 ISOamso -->
- initialMap.put("\u2111", "ℑ"); // blackletter capital I = imaginary part,U+2111 ISOamso -->
- initialMap.put("\u211C", "ℜ"); // blackletter capital R = real part symbol,U+211C ISOamso -->
- initialMap.put("\u2122", "™"); // trade mark sign, U+2122 ISOnum -->
- initialMap.put("\u2135", "ℵ"); // alef symbol = first transfinite cardinal,U+2135 NEW -->
- //
- //
- initialMap.put("\u2190", "←"); // leftwards arrow, U+2190 ISOnum -->
- initialMap.put("\u2191", "↑"); // upwards arrow, U+2191 ISOnum-->
- initialMap.put("\u2192", "→"); // rightwards arrow, U+2192 ISOnum -->
- initialMap.put("\u2193", "↓"); // downwards arrow, U+2193 ISOnum -->
- initialMap.put("\u2194", "↔"); // left right arrow, U+2194 ISOamsa -->
- initialMap.put("\u21B5", "↵"); // downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
- initialMap.put("\u21D0", "⇐"); // leftwards double arrow, U+21D0 ISOtech -->
- //
- initialMap.put("\u21D1", "⇑"); // upwards double arrow, U+21D1 ISOamsa -->
- initialMap.put("\u21D2", "⇒"); // rightwards double arrow,U+21D2 ISOtech -->
- //
- initialMap.put("\u21D3", "⇓"); // downwards double arrow, U+21D3 ISOamsa -->
- initialMap.put("\u21D4", "⇔"); // left right double arrow,U+21D4 ISOamsa -->
- //
- initialMap.put("\u2200", "∀"); // for all, U+2200 ISOtech -->
- initialMap.put("\u2202", "∂"); // partial differential, U+2202 ISOtech -->
- initialMap.put("\u2203", "∃"); // there exists, U+2203 ISOtech -->
- initialMap.put("\u2205", "∅"); // empty set = null set = diameter,U+2205 ISOamso -->
- initialMap.put("\u2207", "∇"); // nabla = backward difference,U+2207 ISOtech -->
- initialMap.put("\u2208", "∈"); // element of, U+2208 ISOtech -->
- initialMap.put("\u2209", "∉"); // not an element of, U+2209 ISOtech -->
- initialMap.put("\u220B", "∋"); // contains as member, U+220B ISOtech -->
- //
- initialMap.put("\u220F", "∏"); // n-ary product = product sign,U+220F ISOamsb -->
- //
- initialMap.put("\u2211", "∑"); // n-ary summation, U+2211 ISOamsb -->
- //
- initialMap.put("\u2212", "−"); // minus sign, U+2212 ISOtech -->
- initialMap.put("\u2217", "∗"); // asterisk operator, U+2217 ISOtech -->
- initialMap.put("\u221A", "√"); // square root = radical sign,U+221A ISOtech -->
- initialMap.put("\u221D", "∝"); // proportional to, U+221D ISOtech -->
- initialMap.put("\u221E", "∞"); // infinity, U+221E ISOtech -->
- initialMap.put("\u2220", "∠"); // angle, U+2220 ISOamso -->
- initialMap.put("\u2227", "∧"); // logical and = wedge, U+2227 ISOtech -->
- initialMap.put("\u2228", "∨"); // logical or = vee, U+2228 ISOtech -->
- initialMap.put("\u2229", "∩"); // intersection = cap, U+2229 ISOtech -->
- initialMap.put("\u222A", "∪"); // union = cup, U+222A ISOtech -->
- initialMap.put("\u222B", "∫"); // integral, U+222B ISOtech -->
- initialMap.put("\u2234", "∴"); // therefore, U+2234 ISOtech -->
- initialMap.put("\u223C", "∼"); // tilde operator = varies with = similar to,U+223C ISOtech -->
- //
- initialMap.put("\u2245", "≅"); // approximately equal to, U+2245 ISOtech -->
- initialMap.put("\u2248", "≈"); // almost equal to = asymptotic to,U+2248 ISOamsr -->
- initialMap.put("\u2260", "≠"); // not equal to, U+2260 ISOtech -->
- initialMap.put("\u2261", "≡"); // identical to, U+2261 ISOtech -->
- initialMap.put("\u2264", "≤"); // less-than or equal to, U+2264 ISOtech -->
- initialMap.put("\u2265", "≥"); // greater-than or equal to,U+2265 ISOtech -->
- initialMap.put("\u2282", "⊂"); // subset of, U+2282 ISOtech -->
- initialMap.put("\u2283", "⊃"); // superset of, U+2283 ISOtech -->
- // ,
- initialMap.put("\u2284", "⊄"); // not a subset of, U+2284 ISOamsn -->
- initialMap.put("\u2286", "⊆"); // subset of or equal to, U+2286 ISOtech -->
- initialMap.put("\u2287", "⊇"); // superset of or equal to,U+2287 ISOtech -->
- initialMap.put("\u2295", "⊕"); // circled plus = direct sum,U+2295 ISOamsb -->
- initialMap.put("\u2297", "⊗"); // circled times = vector product,U+2297 ISOamsb -->
- initialMap.put("\u22A5", "⊥"); // up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
- initialMap.put("\u22C5", "⋅"); // dot operator, U+22C5 ISOamsb -->
- //
- //
- initialMap.put("\u2308", "⌈"); // left ceiling = apl upstile,U+2308 ISOamsc -->
- initialMap.put("\u2309", "⌉"); // right ceiling, U+2309 ISOamsc -->
- initialMap.put("\u230A", "⌊"); // left floor = apl downstile,U+230A ISOamsc -->
- initialMap.put("\u230B", "⌋"); // right floor, U+230B ISOamsc -->
- initialMap.put("\u2329", "〈"); // left-pointing angle bracket = bra,U+2329 ISOtech -->
- //
- initialMap.put("\u232A", "〉"); // right-pointing angle bracket = ket,U+232A ISOtech -->
- //
- //
- initialMap.put("\u25CA", "◊"); // lozenge, U+25CA ISOpub -->
- //
- initialMap.put("\u2660", "♠"); // black spade suit, U+2660 ISOpub -->
- //
- initialMap.put("\u2663", "♣"); // black club suit = shamrock,U+2663 ISOpub -->
- initialMap.put("\u2665", "♥"); // black heart suit = valentine,U+2665 ISOpub -->
- initialMap.put("\u2666", "♦"); // black diamond suit, U+2666 ISOpub -->
-
- //
- initialMap.put("\u0152", "Œ"); // -- latin capital ligature OE,U+0152 ISOlat2 -->
- initialMap.put("\u0153", "œ"); // -- latin small ligature oe, U+0153 ISOlat2 -->
- //
- initialMap.put("\u0160", "Š"); // -- latin capital letter S with caron,U+0160 ISOlat2 -->
- initialMap.put("\u0161", "š"); // -- latin small letter s with caron,U+0161 ISOlat2 -->
- initialMap.put("\u0178", "Ÿ"); // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
- //
- initialMap.put("\u02C6", "ˆ"); // -- modifier letter circumflex accent,U+02C6 ISOpub -->
- initialMap.put("\u02DC", "˜"); // small tilde, U+02DC ISOdia -->
- //
- initialMap.put("\u2002", " "); // en space, U+2002 ISOpub -->
- initialMap.put("\u2003", " "); // em space, U+2003 ISOpub -->
- initialMap.put("\u2009", " "); // thin space, U+2009 ISOpub -->
- initialMap.put("\u200C", ""); // zero width non-joiner,U+200C NEW RFC 2070 -->
- initialMap.put("\u200D", ""); // zero width joiner, U+200D NEW RFC 2070 -->
- initialMap.put("\u200E", ""); // left-to-right mark, U+200E NEW RFC 2070 -->
- initialMap.put("\u200F", ""); // right-to-left mark, U+200F NEW RFC 2070 -->
- initialMap.put("\u2013", "–"); // en dash, U+2013 ISOpub -->
- initialMap.put("\u2014", "—"); // em dash, U+2014 ISOpub -->
- initialMap.put("\u2018", "‘"); // left single quotation mark,U+2018 ISOnum -->
- initialMap.put("\u2019", "’"); // right single quotation mark,U+2019 ISOnum -->
- initialMap.put("\u201A", "‚"); // single low-9 quotation mark, U+201A NEW -->
- initialMap.put("\u201C", "“"); // left double quotation mark,U+201C ISOnum -->
- initialMap.put("\u201D", "”"); // right double quotation mark,U+201D ISOnum -->
- initialMap.put("\u201E", "„"); // double low-9 quotation mark, U+201E NEW -->
- initialMap.put("\u2020", "†"); // dagger, U+2020 ISOpub -->
- initialMap.put("\u2021", "‡"); // double dagger, U+2021 ISOpub -->
- initialMap.put("\u2030", "‰"); // per mille sign, U+2030 ISOtech -->
- initialMap.put("\u2039", "‹"); // single left-pointing angle quotation mark,U+2039 ISO proposed -->
- //
- initialMap.put("\u203A", "›"); // single right-pointing angle quotation mark,U+203A ISO proposed -->
- //
- initialMap.put("\u20AC", "€"); // -- euro sign, U+20AC NEW -->
- HTML40_EXTENDED_ESCAPE = Collections.unmodifiableMap(initialMap);
- }
-
- /**
- * Reverse of {@link #HTML40_EXTENDED_ESCAPE} for unescaping purposes.
- */
- public static final Map HTML40_EXTENDED_UNESCAPE;
- static {
- HTML40_EXTENDED_UNESCAPE = Collections.unmodifiableMap(invert(HTML40_EXTENDED_ESCAPE));
- }
-
- /**
- * A Map<CharSequence, CharSequence> to escape the basic XML and HTML
- * character entities.
- *
- * Namely: {@code " & < >}
- */
- public static final Map BASIC_ESCAPE;
- static {
- final Map initialMap = new HashMap<>();
- initialMap.put("\"", """); // " - double-quote
- initialMap.put("&", "&"); // & - ampersand
- initialMap.put("<", "<"); // < - less-than
- initialMap.put(">", ">"); // > - greater-than
- BASIC_ESCAPE = Collections.unmodifiableMap(initialMap);
- }
-
- /**
- * Reverse of {@link #BASIC_ESCAPE} for unescaping purposes.
- */
- public static final Map BASIC_UNESCAPE;
- static {
- BASIC_UNESCAPE = Collections.unmodifiableMap(invert(BASIC_ESCAPE));
- }
-
- /**
- * A Map<CharSequence, CharSequence> to escape the apostrophe character to
- * its XML character entity.
- */
- public static final Map APOS_ESCAPE;
- static {
- final Map initialMap = new HashMap<>();
- initialMap.put("'", "'"); // XML apostrophe
- APOS_ESCAPE = Collections.unmodifiableMap(initialMap);
- }
-
- /**
- * Reverse of {@link #APOS_ESCAPE} for unescaping purposes.
- */
- public static final Map APOS_UNESCAPE;
- static {
- APOS_UNESCAPE = Collections.unmodifiableMap(invert(APOS_ESCAPE));
- }
-
- /**
- * A Map<CharSequence, CharSequence> to escape the Java
- * control characters.
- *
- * Namely: {@code \b \n \t \f \r}
- */
- public static final Map JAVA_CTRL_CHARS_ESCAPE;
- static {
- final Map initialMap = new HashMap<>();
- initialMap.put("\b", "\\b");
- initialMap.put("\n", "\\n");
- initialMap.put("\t", "\\t");
- initialMap.put("\f", "\\f");
- initialMap.put("\r", "\\r");
- JAVA_CTRL_CHARS_ESCAPE = Collections.unmodifiableMap(initialMap);
- }
-
- /**
- * Reverse of {@link #JAVA_CTRL_CHARS_ESCAPE} for unescaping purposes.
- */
- public static final Map JAVA_CTRL_CHARS_UNESCAPE;
- static {
- JAVA_CTRL_CHARS_UNESCAPE = Collections.unmodifiableMap(invert(JAVA_CTRL_CHARS_ESCAPE));
- }
-
- /**
- * Used to invert an escape Map into an unescape Map.
- * @param map Map<String, String> to be inverted
- * @return Map<String, String> inverted array
- */
- public static Map invert(final Map map) {
- final Map newMap = new HashMap<>();
- for (final Map.Entry pair : map.entrySet()) {
- newMap.put(pair.getValue(), pair.getKey());
- }
- return newMap;
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/JavaUnicodeEscaper.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/JavaUnicodeEscaper.java
deleted file mode 100644
index c7c83a54..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/JavaUnicodeEscaper.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-/**
- * Translates codepoints to their Unicode escaped value suitable for Java source.
- *
- * @since 1.0
- */
-public class JavaUnicodeEscaper extends UnicodeEscaper {
-
- /**
- *
- * Constructs a JavaUnicodeEscaper above the specified value (exclusive).
- *
- *
- * @param codepoint
- * above which to escape
- * @return the newly created {@code UnicodeEscaper} instance
- */
- public static JavaUnicodeEscaper above(final int codepoint) {
- return outsideOf(0, codepoint);
- }
-
- /**
- *
- * Constructs a JavaUnicodeEscaper below the specified value (exclusive).
- *
- *
- * @param codepoint
- * below which to escape
- * @return the newly created {@code UnicodeEscaper} instance
- */
- public static JavaUnicodeEscaper below(final int codepoint) {
- return outsideOf(codepoint, Integer.MAX_VALUE);
- }
-
- /**
- *
- * Constructs a JavaUnicodeEscaper between the specified values (inclusive).
- *
- *
- * @param codepointLow
- * above which to escape
- * @param codepointHigh
- * below which to escape
- * @return the newly created {@code UnicodeEscaper} instance
- */
- public static JavaUnicodeEscaper between(final int codepointLow, final int codepointHigh) {
- return new JavaUnicodeEscaper(codepointLow, codepointHigh, true);
- }
-
- /**
- *
- * Constructs a JavaUnicodeEscaper outside of the specified values (exclusive).
- *
- *
- * @param codepointLow
- * below which to escape
- * @param codepointHigh
- * above which to escape
- * @return the newly created {@code UnicodeEscaper} instance
- */
- public static JavaUnicodeEscaper outsideOf(final int codepointLow, final int codepointHigh) {
- return new JavaUnicodeEscaper(codepointLow, codepointHigh, false);
- }
-
- /**
- *
- * Constructs a JavaUnicodeEscaper for the specified range. This is the underlying method for the
- * other constructors/builders. The below and above boundaries are inclusive when
- * between is true and exclusive when it is false.
- *
- *
- * @param below
- * int value representing the lowest codepoint boundary
- * @param above
- * int value representing the highest codepoint boundary
- * @param between
- * whether to escape between the boundaries or outside them
- */
- public JavaUnicodeEscaper(final int below, final int above, final boolean between) {
- super(below, above, between);
- }
-
- /**
- * Converts the given codepoint to a hex string of the form {@code "\\uXXXX\\uXXXX"}.
- *
- * @param codepoint
- * a Unicode code point
- * @return the hex string for the given codepoint
- */
- @Override
- protected String toUtf16Escape(final int codepoint) {
- final char[] surrogatePair = Character.toChars(codepoint);
- return "\\u" + hex(surrogatePair[0]) + "\\u" + hex(surrogatePair[1]);
- }
-
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/LookupTranslator.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/LookupTranslator.java
deleted file mode 100644
index 701e57c9..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/LookupTranslator.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.security.InvalidParameterException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-/**
- * Translates a value using a lookup table.
- *
- * @since 1.0
- */
-public class LookupTranslator extends CharSequenceTranslator {
-
- /** The mapping to be used in translation. */
- private final Map lookupMap;
- /** The first character of each key in the lookupMap. */
- private final HashSet prefixSet;
- /** The length of the shortest key in the lookupMap. */
- private final int shortest;
- /** The length of the longest key in the lookupMap. */
- private final int longest;
-
- /**
- * Define the lookup table to be used in translation
- *
- * Note that, as of Lang 3.1 (the origin of this code), the key to the lookup
- * table is converted to a java.lang.String. This is because we need the key
- * to support hashCode and equals(Object), allowing it to be the key for a
- * HashMap. See LANG-882.
- *
- * @param lookupMap Map<CharSequence, CharSequence> table of translator
- * mappings
- */
- public LookupTranslator(final Map lookupMap) {
- if (lookupMap == null) {
- throw new InvalidParameterException("lookupMap cannot be null");
- }
- this.lookupMap = new HashMap<>();
- this.prefixSet = new HashSet<>();
- int currentShortest = Integer.MAX_VALUE;
- int currentLongest = 0;
-
- for (final Map.Entry pair : lookupMap.entrySet()) {
- this.lookupMap.put(pair.getKey().toString(), pair.getValue().toString());
- this.prefixSet.add(pair.getKey().charAt(0));
- final int sz = pair.getKey().length();
- if (sz < currentShortest) {
- currentShortest = sz;
- }
- if (sz > currentLongest) {
- currentLongest = sz;
- }
- }
- this.shortest = currentShortest;
- this.longest = currentLongest;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- // check if translation exists for the input at position index
- if (prefixSet.contains(input.charAt(index))) {
- int max = longest;
- if (index + longest > input.length()) {
- max = input.length() - index;
- }
- // implement greedy algorithm by trying maximum match first
- for (int i = max; i >= shortest; i--) {
- final CharSequence subSeq = input.subSequence(index, index + i);
- final String result = lookupMap.get(subSeq.toString());
-
- if (result != null) {
- out.write(result);
- return i;
- }
- }
- }
- return 0;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityEscaper.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityEscaper.java
deleted file mode 100644
index 01456a8e..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityEscaper.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-
-import com.joyy.stringescape.Range;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Translates codepoints to their XML numeric entity escaped value.
- *
- * @since 1.0
- */
-public class NumericEntityEscaper extends CodePointTranslator {
-
- /** whether to escape between the boundaries or outside them. */
- private final boolean between;
- /** range from lowest codepoint to highest codepoint. */
- private final Range range;
- /**
- * Constructs a NumericEntityEscaper for the specified range. This is
- * the underlying method for the other constructors/builders. The below
- * and above boundaries are inclusive when between is
- * true and exclusive when it is false.
- *
- * @param below int value representing the lowest codepoint boundary
- * @param above int value representing the highest codepoint boundary
- * @param between whether to escape between the boundaries or outside them
- */
- private NumericEntityEscaper(final int below, final int above, final boolean between) {
- this.range = Range.between(below, above);
- this.between = between;
- }
-
- /**
- * Constructs a NumericEntityEscaper for all characters.
- */
- public NumericEntityEscaper() {
- this(0, Integer.MAX_VALUE, true);
- }
-
- /**
- * Constructs a NumericEntityEscaper below the specified value (exclusive).
- *
- * @param codepoint below which to escape
- * @return the newly created {@code NumericEntityEscaper} instance
- */
- public static NumericEntityEscaper below(final int codepoint) {
- return outsideOf(codepoint, Integer.MAX_VALUE);
- }
-
- /**
- * Constructs a NumericEntityEscaper above the specified value (exclusive).
- *
- * @param codepoint above which to escape
- * @return the newly created {@code NumericEntityEscaper} instance
- */
- public static NumericEntityEscaper above(final int codepoint) {
- return outsideOf(0, codepoint);
- }
-
- /**
- * Constructs a NumericEntityEscaper between the specified values (inclusive).
- *
- * @param codepointLow above which to escape
- * @param codepointHigh below which to escape
- * @return the newly created {@code NumericEntityEscaper} instance
- */
- public static NumericEntityEscaper between(final int codepointLow, final int codepointHigh) {
- return new NumericEntityEscaper(codepointLow, codepointHigh, true);
- }
-
- /**
- * Constructs a NumericEntityEscaper outside of the specified values (exclusive).
- *
- * @param codepointLow below which to escape
- * @param codepointHigh above which to escape
- * @return the newly created {@code NumericEntityEscaper} instance
- */
- public static NumericEntityEscaper outsideOf(final int codepointLow, final int codepointHigh) {
- return new NumericEntityEscaper(codepointLow, codepointHigh, false);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean translate(final int codepoint, final Writer out) throws IOException {
- if (this.between != this.range.contains(codepoint)) {
- return false;
- }
- out.write("");
- out.write(Integer.toString(codepoint, 10));
- out.write(';');
- return true;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityUnescaper.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityUnescaper.java
deleted file mode 100644
index f23d1244..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/NumericEntityUnescaper.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.EnumSet;
-
-/**
- * Translate XML numeric entities of the form &#[xX]?\d+;? to
- * the specific codepoint.
- *
- * Note that the semi-colon is optional.
- *
- * @since 1.0
- */
-public class NumericEntityUnescaper extends CharSequenceTranslator {
-
- /** NumericEntityUnescaper option enum. */
- public enum OPTION { semiColonRequired, semiColonOptional, errorIfNoSemiColon }
-
- /** EnumSet of OPTIONS, given from the constructor. */
- private final EnumSet options;
-
- /**
- * Create a UnicodeUnescaper.
- *
- * The constructor takes a list of options, only one type of which is currently
- * available (whether to allow, error or ignore the semi-colon on the end of a
- * numeric entity to being missing).
- *
- * For example, to support numeric entities without a ';':
- * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.semiColonOptional)
- * and to throw an IllegalArgumentException when they're missing:
- * new NumericEntityUnescaper(NumericEntityUnescaper.OPTION.errorIfNoSemiColon)
- *
- * Note that the default behaviour is to ignore them.
- *
- * @param options to apply to this unescaper
- */
- public NumericEntityUnescaper(final OPTION... options) {
- if (options.length > 0) {
- this.options = EnumSet.copyOf(Arrays.asList(options));
- } else {
- this.options = EnumSet.copyOf(Arrays.asList(new OPTION[] {OPTION.semiColonRequired}));
- }
- }
-
- /**
- * Whether the passed in option is currently set.
- *
- * @param option to check state of
- * @return whether the option is set
- */
- public boolean isSet(final OPTION option) {
- return options != null && options.contains(option);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- final int seqEnd = input.length();
- // Uses -2 to ensure there is something after the
- if (input.charAt(index) == '&' && index < seqEnd - 2 && input.charAt(index + 1) == '#') {
- int start = index + 2;
- boolean isHex = false;
-
- final char firstChar = input.charAt(start);
- if (firstChar == 'x' || firstChar == 'X') {
- start++;
- isHex = true;
-
- // Check there's more than just an x after the
- if (start == seqEnd) {
- return 0;
- }
- }
-
- int end = start;
- // Note that this supports character codes without a ; on the end
- while (end < seqEnd && (input.charAt(end) >= '0' && input.charAt(end) <= '9'
- || input.charAt(end) >= 'a' && input.charAt(end) <= 'f'
- || input.charAt(end) >= 'A' && input.charAt(end) <= 'F')) {
- end++;
- }
-
- final boolean semiNext = end != seqEnd && input.charAt(end) == ';';
-
- if (!semiNext) {
- if (isSet(OPTION.semiColonRequired)) {
- return 0;
- }
- if (isSet(OPTION.errorIfNoSemiColon)) {
- throw new IllegalArgumentException("Semi-colon required at end of numeric entity");
- }
- }
-
- int entityValue;
- try {
- if (isHex) {
- entityValue = Integer.parseInt(input.subSequence(start, end).toString(), 16);
- } else {
- entityValue = Integer.parseInt(input.subSequence(start, end).toString(), 10);
- }
- } catch (final NumberFormatException nfe) {
- return 0;
- }
-
- if (entityValue > 0xFFFF) {
- final char[] chrs = Character.toChars(entityValue);
- out.write(chrs[0]);
- out.write(chrs[1]);
- } else {
- out.write(entityValue);
- }
-
- return 2 + end - start + (isHex ? 1 : 0) + (semiNext ? 1 : 0);
- }
- return 0;
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/OctalUnescaper.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/OctalUnescaper.java
deleted file mode 100644
index 48a73ede..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/OctalUnescaper.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Translate escaped octal Strings back to their octal values.
- *
- * For example, "\45" should go back to being the specific value (a %).
- *
- * Note that this currently only supports the viable range of octal for Java; namely
- * 1 to 377. This is because parsing Java is the main use case.
- *
- * @since 1.0
- */
-public class OctalUnescaper extends CharSequenceTranslator {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- final int remaining = input.length() - index - 1; // how many characters left, ignoring the first \
- final StringBuilder builder = new StringBuilder();
- if (input.charAt(index) == '\\' && remaining > 0 && isOctalDigit(input.charAt(index + 1))) {
- final int next = index + 1;
- final int next2 = index + 2;
- final int next3 = index + 3;
-
- // we know this is good as we checked it in the if block above
- builder.append(input.charAt(next));
-
- if (remaining > 1 && isOctalDigit(input.charAt(next2))) {
- builder.append(input.charAt(next2));
- if (remaining > 2 && isZeroToThree(input.charAt(next)) && isOctalDigit(input.charAt(next3))) {
- builder.append(input.charAt(next3));
- }
- }
-
- out.write(Integer.parseInt(builder.toString(), 8));
- return 1 + builder.length();
- }
- return 0;
- }
-
- /**
- * Checks if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7.
- * @param ch the char to check
- * @return true if the given char is the character representation of one of the digits from 0 to 7
- */
- private boolean isOctalDigit(final char ch) {
- return ch >= '0' && ch <= '7';
- }
-
- /**
- * Checks if the given char is the character representation of one of the digit from 0 to 3.
- * @param ch the char to check
- * @return true if the given char is the character representation of one of the digits from 0 to 3
- */
- private boolean isZeroToThree(final char ch) {
- return ch >= '0' && ch <= '3';
- }
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/SinglePassTranslator.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/SinglePassTranslator.java
deleted file mode 100644
index b0ef2487..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/SinglePassTranslator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Abstract translator for processing whole input in single pass.
- * Handles initial index checking and counting of returned code points.
- */
-abstract class SinglePassTranslator extends CharSequenceTranslator {
-
- @Override
- public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
- if (index != 0) {
- throw new IllegalArgumentException(getClassName() + ".translate(final CharSequence input, final int "
- + "index, final Writer out) can not handle a non-zero index.");
- }
-
- translateWhole(input, out);
-
- return Character.codePointCount(input, index, input.length());
- }
-
- /**
- * A utility method to be used in the {@link #translate(CharSequence, int, Writer)} method.
- *
- * @return the name of this or the extending class.
- */
- private String getClassName() {
- final Class extends SinglePassTranslator> clazz = this.getClass();
- return clazz.isAnonymousClass() ? clazz.getName() : clazz.getSimpleName();
- }
-
- /**
- * Translate whole set of code points passed in input.
- *
- * @param input CharSequence that is being translated
- * @param out Writer to translate the text to
- * @throws IOException if and only if the Writer produces an IOException
- */
- abstract void translateWhole(CharSequence input, Writer out) throws IOException;
-}
diff --git a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/UnicodeEscaper.java b/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/UnicodeEscaper.java
deleted file mode 100644
index affd2fea..00000000
--- a/android/AndroidProject/stringescape/src/main/java/com/joyy/stringescape/translate/UnicodeEscaper.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package com.joyy.stringescape.translate;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Translates codepoints to their Unicode escaped value.
- *
- * @since 1.0
- */
-public class UnicodeEscaper extends CodePointTranslator {
-
- /** int value representing the lowest codepoint boundary. */
- private final int below;
- /** int value representing the highest codepoint boundary. */
- private final int above;
- /** whether to escape between the boundaries or outside them. */
- private final boolean between;
-
- /**
- * Constructs a