diff --git a/.gitignore b/.gitignore index 224e7f0..0b35c6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,106 @@ -.pc/ +# Created by https://www.gitignore.io/api/java,eclipse +# Edit at https://www.gitignore.io/?templates=java,eclipse + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders +.pmd + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +### Eclipse Patch ### +# Eclipse Core +.project + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Annotation Processing +.apt_generated + +.sts4-cache/ + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# End of https://www.gitignore.io/api/java,eclipse + +/target +/*/target + +.flattened-pom.xml + +*pom.xml.versionsBackup \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ee0373e..a415163 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,19 +1,111 @@ -image: openjdk:11-stretch +image: eclipse-temurin:21 -stages: - - build +variables: + # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log. + # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work. + MAVEN_OPTS: | + -Dhttps.protocols=TLSv1.3,TLSv1.2 + -Djdk.tls.client.protocols=TLSv1.3,TLSv1.2 + -Dorg.slf4j.simpleLogger.showDateTime=true + -Djava.awt.headless=true + -Xss4m + MAVEN_CLI_OPTS: | + --batch-mode + --strict-checksums + --errors + --show-version + --no-transfer-progress + -DinstallAtEnd=true + -DdeployAtEnd=true + -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository + -Dmaven.user.home=$CI_PROJECT_DIR/.m2 -cache: +# Cache downloaded dependencies and plugins between builds. +# To keep cache across branches add 'key: "$CI_JOB_NAME"' +cache: &global_cache + key: + files: + - pom.xml paths: - - .m2/ + - .m2 + - .mvn -variables: - M2_HOME: ".m2/maven" - MAVEN_OPTS: "-Dmaven.repo.local=.m2" - GITLAB_BASE_URL: "https://gitlab.com" +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS' + when: never + - if: '$CI_COMMIT_BRANCH' + +stages: + - build + - test + - check build: stage: build script: - - bash mvnw clean verify -P safer + - ./mvnw $MAVEN_CLI_OPTS package -P codegen -DskipTests + artifacts: + paths: + - "*/target/" + +tests: + stage: test + needs: + - job: build + artifacts: true + parallel: + matrix: + - JDK_IMAGE: + - azul/zulu-openjdk:8 + - azul/zulu-openjdk:11 + - azul/zulu-openjdk:17 + - azul/zulu-openjdk:21 + - azul/zulu-openjdk:22 + - openjdk:23-ea-oraclelinux9 + image: $JDK_IMAGE + script: + - ./mvnw $MAVEN_CLI_OPTS verify -Denforcer.skip=true + cache: + # inherit all global cache settings + <<: *global_cache + policy: pull + artifacts: + reports: + junit: + - "*/target/surefire-reports/TEST-*.xml" + - "**/target/junit-platform/TEST-*.xml" +sonarcloud-check: + stage: check + cache: + key: "${CI_JOB_NAME}" + paths: + - .sonar/cache + variables: + GIT_STRATEGY: clone + GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task + SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache + script: + - | + ./mvnw $MAVEN_CLI_OPTS verify sonar:sonar \ + -Dsonar.qualitygate.wait=true -Dsonar.organization=ongresinc \ + -Dsonar.coverage.jacoco.xmlReportPaths="${CI_PROJECT_DIR}/coverage-report/target/site/jacoco-aggregate/jacoco.xml" \ + -P coverage + only: + - merge_requests + - develop + - main + +static-checks: + stage: check + needs: + - job: build + artifacts: true + script: + - ./mvnw $MAVEN_CLI_OPTS verify -P checks -DskipTests + cache: + # inherit all global cache settings + <<: *global_cache + policy: pull diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 0000000..7fa4242 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1 @@ +--strict-checksums diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java index c32394f..84d1e60 100644 --- a/.mvn/wrapper/MavenWrapperDownloader.java +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -1,117 +1,98 @@ /* - * Copyright 2007-present the original author or authors. + * 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 * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 * - * 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. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.5"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; +import java.io.IOException; +import java.io.InputStream; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; +public final class MavenWrapperDownloader +{ + private static final String WRAPPER_VERSION = "3.2.0"; - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) ); - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + public static void main( String[] args ) + { + log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION ); - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } + if ( args.length != 2 ) + { + System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" ); + System.exit( 1 ); } - System.out.println("- Downloading from: " + url); - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } + try + { + log( " - Downloader started" ); + final URL wrapperUrl = new URL( args[0] ); + final String jarPath = args[1].replace( "..", "" ); // Sanitize path + final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize(); + downloadFileFromURL( wrapperUrl, wrapperJarPath ); + log( "Done" ); } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); + catch ( IOException e ) + { + System.err.println( "- Error downloading: " + e.getMessage() ); + if ( VERBOSE ) + { + e.printStackTrace(); + } + System.exit( 1 ); } } - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { + private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath ) + throws IOException + { + log( " - Downloading to: " + wrapperJarPath ); + if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null ) + { + final String username = System.getenv( "MVNW_USERNAME" ); + final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray(); + Authenticator.setDefault( new Authenticator() + { @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); + protected PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication( username, password ); } - }); + } ); + } + try ( InputStream inStream = wrapperUrl.openStream() ) + { + Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING ); + } + log( " - Downloader complete" ); + } + + private static void log( String msg ) + { + if ( VERBOSE ) + { + System.out.println( msg ); } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); } } diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index fa87ad7..346d645 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,18 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar +# 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. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/.settings/.gitignore b/.settings/.gitignore deleted file mode 100644 index 0924da4..0000000 --- a/.settings/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/org.eclipse.m2e.core.prefs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a3e26a1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog +All notable changes to this project will be documented in this file. + +## [Unreleased] + +## [2.1] - 2024-04-01 +### :bug: Bug Fixes +- `Stringprep::getProvider` was not working on the module path. + +### :sparkles: New features +- The Profile interface now has overloaded methods with `char[]` versions. + +### :building_construction: Improvements +- The Java modules profiles `com.ongres.saslprep` and `com.ongres.nameprep` have implied readability with `com.ongres.stringprep`. +- Exports the packages of the profiles in the module declaration to allow creating instances without the ServiceLoader lookup. +- Introduce the annotation `@ProfileName` to declare the name of the profile used for ServiceLoader lookup. +- Now the released jars are reproducible. +- Publish CycloneDX SBOM. + +## [2.0] - 2021-02-01 +### :boom: Breaking changes +- Full rewrite of the `stringprep` implementation, this release is compatible with Java 8+. + +### :sparkles: New features +- The stringprep profiles can be created by implementing the `Profile` interface. +- New module `nameprep` implementing the stringprep `Profile`. +- Create Multi-release Modular JARs, the modules names are: + - `com.ongres.stringprep` + - `com.ongres.saslprep` + - `com.ongres.nameprep` + +### :building_construction: Improvements +- Refactor of the `stringprep` implementation to make it extensible and modular, now this implemenation is considered feature-complete. +- Change the module `saslprep` to implement the stringprep `Profile` interface. + +[Unreleased]: https://gitlab.com/ongresinc/stringprep/-/compare/2.0...main +[2.0]: https://gitlab.com/ongresinc/stringprep/-/compare/1.1...2.0 diff --git a/LICENSE b/LICENSE index 84b3fe0..809c9ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2019, OnGres. +Copyright 2019, OnGres, Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/NOTICE b/NOTICE deleted file mode 100644 index c36a807..0000000 --- a/NOTICE +++ /dev/null @@ -1,9 +0,0 @@ -This source code includes source code from other projects. Below the list -of the project were the source code has been copied together with the -path of the copied source files, their license, their notice (if any) -and the modification that have been done. - -1. org.apache.velocity with the artifacts velocity and velocity-tools - -Module codegenerator needs these dependencies to generate the class StringPrep dynamically. -The dependency org.apache.velocity is licensed under the Apache 2.0 license (see thirdparty/velocity-LICENSE). \ No newline at end of file diff --git a/README.md b/README.md index 54f4237..1f34d2e 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,110 @@ -# StringPrep and SaslPrep implementation +# Stringprep (RFC 3454) Java implementation + +> Preparation of Internationalized Strings ("stringprep") ## Overview -StringPrep is the preparation of internationalized strings -([stringprep, RFC 3454](https://tools.ietf.org/html/rfc3454)). -SaslPrep is a profile of stringprep for user names and passwords -([saslprep, RFC 4013](https://tools.ietf.org/html/rfc4013)). +This project implements the [RFC 3454](https://tools.ietf.org/html/rfc3454) Preparation of Internationalized Strings ("stringprep") in pure Java. -## Goals +[![Maven Central](https://img.shields.io/badge/maven--central-stringprep-informational?style=for-the-badge&logo=apache-maven&logoColor=red)](https://maven-badges.herokuapp.com/maven-central/com.ongres.stringprep/stringprep) -This project aims to provide a implementation of these algorithms. -It is written in Java and provided in a modular, re-usable way, independent of -other software or programs. +The stringprep protocol does not stand on its own; it has to be used by other protocols at precisely-defined places in those other protocols. -Current functionality includes: +## Profiles -* Parsers with the different steps for preparing string. The data is obtained from a file with the rules of the RFC. -* StringPrep dynamic class with the different types of: map, normalize, prohibit and check bidi possibles. -* SaslPrep with the specific steps of StringPrep. -* Tests with the RFC example and several tests of each steps. +### SASLprep (RFC 4013) + +`SASLprep` is a profile of stringprep for user names and passwords ([RFC 4013](https://tools.ietf.org/html/rfc4013)). + +Import Maven dependency: + +[![Maven Central](https://img.shields.io/badge/maven--central-saslprep-informational?style=for-the-badge&logo=apache-maven&logoColor=red)](https://maven-badges.herokuapp.com/maven-central/com.ongres.stringprep/saslprep) + +```xml + + com.ongres.stringprep + saslprep + 2.0 + +``` + +### Nameprep (RFC 3491) + +`Nameprep` is a Stringprep Profile for Internationalized Domain Names (IDN) ([RFC 3491](https://tools.ietf.org/html/rfc3491)). + +Import Maven dependency: + +[![Maven Central](https://img.shields.io/badge/maven--central-nameprep-informational?style=for-the-badge&logo=apache-maven&logoColor=red)](https://maven-badges.herokuapp.com/maven-central/com.ongres.stringprep/nameprep) -## Saslprep +```xml + + com.ongres.stringprep + nameprep + 2.0 + +``` -'saslprep' is the module that contains the saslprep profile of StringPrep. -Import maven dependency: +## Usage - - com.ongres.stringprep - saslprep - - +The normal usage is to import the dependency of the Stringprep profile to use, and lookup the provider service that contains the profile. -## Contributing +### Example: +Import the `SASLprep` dependency, this transitively imports the `Stringprep` dependency. +```xml + + com.ongres.stringprep + saslprep + 2.0 + +``` -Please submit [Merge Requests](https://gitlab.com/ongresinc/stringprep) for code contributions. -Make sure to compile with `mvn compile -P safer` before submitting a MR. +Get the `SASLprep` provider service: +```java +Profile saslPrep = Stringprep.getProvider("SASLprep"); +String prepared = saslPrep.prepareStored("I\u00ADX \u2168"); +prepared.equals("IX IX"); // true +``` -Releases (on the master branch only) must be verified with: +You could also (only) use the stringprep dependency to create your own profiles by implementing the `Profile` interface, just override the `profile()` method with the set of options. - mvn -P safer -Pmaster-branch \ No newline at end of file +Anonymous on-the-fly profile usage: +```java +Profile saslPrep = () -> EnumSet.of(Option.NORMALIZE_KC, Option.MAP_TO_NOTHING); +String prepared = saslPrep.prepareStored("I\u00ADX ⑳"); +prepared.equals("IX 20"); // true +``` + +> Please note that when two protocols that use different profiles of stringprep interoperate, there may be conflict about what characters are and are not allowed in the final string. Thus, protocol developers should strongly consider re-using existing profiles of stringprep. + +### Java Modules (JPMS): +The Stringprep and profiles implementation are explicit Java modules with the names: + +* `com.ongres.stringprep` +* `com.ongres.saslprep` +* `com.ongres.nameprep` + +If you depend on a specific profile (`saslprep` or `nameprep`) there is an implied readability on `stringprep`, so you will only need to declare in your `module-info.java` the profile module and get the service from the provider. + +Example `module-info.java`: +```java +module test.app { + requires com.ongres.saslprep; +} +``` + +## Goals + +This project aims to provide a implementation of these algorithms. +It is written in Java and provided in a modular, re-usable way, independent of other software or programs. + +Current functionality includes: + +* Parsers with the different steps for preparing string. The data is obtained from files with the rules of the RFC. +* Provide a `Profile` interface working as the base for implementing different profiles of Stringprep. +* Include the preparation of two types of strings "stored strings" and "queries". +* `SASLprep` profile with the specific options of Stringprep. +* `Nameprep` profile with the specific options of Stringprep. +* Tests with the RFC example and several tests of each steps. +* Multi-release Modular JARs, compatible with Java 8+. +* Zero-depdency, each profile depends only on the Stringprep module. +* New Stringprep profiles could be implemented easily and even "on-the-fly". diff --git a/checks/checkstyle-header.txt b/checks/checkstyle-header.txt new file mode 100644 index 0000000..7401973 --- /dev/null +++ b/checks/checkstyle-header.txt @@ -0,0 +1,4 @@ +^\/\*$ +^ \* Copyright \(C\) 20[12]\d OnGres, Inc\.$ +^ \* SPDX-License-Identifier: BSD-2-Clause$ +^ \*\/$ \ No newline at end of file diff --git a/checks/checkstyle-suppressions.xml b/checks/checkstyle-suppressions.xml new file mode 100644 index 0000000..7129fc8 --- /dev/null +++ b/checks/checkstyle-suppressions.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/checks/checkstyle.xml b/checks/checkstyle.xml new file mode 100644 index 0000000..64ddd55 --- /dev/null +++ b/checks/checkstyle.xml @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/checks/pmd-ruleset.xml b/checks/pmd-ruleset.xml new file mode 100644 index 0000000..5542431 --- /dev/null +++ b/checks/pmd-ruleset.xml @@ -0,0 +1,42 @@ + + + + Custom Rules + + .*/target/.* + .*/generated/.* + .*/Tables.java + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/checks/spotbugs-exclude.xml b/checks/spotbugs-exclude.xml new file mode 100644 index 0000000..708a899 --- /dev/null +++ b/checks/spotbugs-exclude.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/codegen/pom.xml b/codegen/pom.xml new file mode 100644 index 0000000..1ed210c --- /dev/null +++ b/codegen/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + com.ongres.stringprep + stringprep-parent + 2.1 + ../parent/pom.xml + + + codegen + Tables Code Generator + Code Generator for StringPrep tables + + + true + ${project.basedir}/../checks + + + + + org.apache.velocity + velocity-engine-core + 2.3 + + + diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/GeneratorCode.java b/codegen/src/main/java/com/ongres/stringprep/codegen/GeneratorCode.java new file mode 100644 index 0000000..bdf40e5 --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/GeneratorCode.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NotDirectoryException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.ongres.stringprep.codegen.parsers.Parser; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; + +/** + * Stringprep tables class generator. + */ +public final class GeneratorCode { + + private GeneratorCode() { + throw new AssertionError(); + } + + /** + * Generate StringPrep class dynamically. + * + * @param args with the path used to generate StringPrep class + * @throws IOException if a RFC file can't be read + */ + public static void main(String[] args) throws IOException { + Path sourceDirectory = Paths.get(System.getProperty("sourceDirectory")).normalize(); + if (!Files.isDirectory(sourceDirectory)) { + throw new NotDirectoryException(sourceDirectory.toString()); + } + + VelocityEngine velocityEngine = new VelocityEngine(); + velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, + RuntimeConstants.RESOURCE_LOADER_CLASS); + velocityEngine.setProperty("resource.loader.class.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + velocityEngine.init(); + + Template template = velocityEngine.getTemplate("templates/StringPrepTables.vm"); + VelocityContext ctx = new VelocityContext(); + ctx.put("parser", new Parser()); + + Path path = sourceDirectory.resolve("com/ongres/stringprep/Tables.java"); + Files.deleteIfExists(path); + try (Writer writer = new OutputStreamWriter(Files.newOutputStream(path), StandardCharsets.UTF_8)) { + template.merge(ctx, writer); + } + } + +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/Parser.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/Parser.java new file mode 100644 index 0000000..d221d3a --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/Parser.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.util.List; +import java.util.Map; + +/** + * List of the tables parsed to the generator engine. + */ +public class Parser { + + public List> getUnassignedCodePoints() { + return ParserUnicodeRepertoires.getUnassignedCodePoints(); + } + + public List getMapToNothing() { + return ParserMappingTables.getMapToNothing(); + } + + public Map> getMapUsedWithNfkc() { + return ParserMappingTables.getMapUsedWithNfkc(); + } + + public Map> getMapUsedWithNoNormalization() { + return ParserMappingTables.getMapUsedWithNoNormalization(); + } + + public List getAsciiSpace() { + return ParserProhibitionTables.getAsciiSpace(); + } + + public List getNonAsciiSpace() { + return ParserProhibitionTables.getNonAsciiSpace(); + } + + public List> getAsciiControl() { + return ParserProhibitionTables.getAsciiControl(); + } + + public List> getNonAsciiControl() { + return ParserProhibitionTables.getNonAsciiControl(); + } + + public List> getPrivateUse() { + return ParserProhibitionTables.getPrivateUse(); + } + + public List> getNonCharacterCodePoints() { + return ParserProhibitionTables.getNonCharacterCodePoints(); + } + + public List> getSurrogateCodes() { + return ParserProhibitionTables.getSurrogateCodes(); + } + + public List> getInappropriatePlainText() { + return ParserProhibitionTables.getInappropriatePlainText(); + } + + public List> getInappropriateCanonicalRepresentation() { + return ParserProhibitionTables.getInappropriateCanonicalRepresentation(); + } + + public List> getChangeDisplayProperties() { + return ParserProhibitionTables.getChangeDisplayProperties(); + } + + public List> getTaggingCharacters() { + return ParserProhibitionTables.getTaggingCharacters(); + } + + public List> getPropertyRorAL() { + return ParserBidirectionalTables.getBidirectionalPropertyRorAL(); + } + + public List> getPropertyL() { + return ParserBidirectionalTables.getBidirectionalPropertyL(); + } +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserBidirectionalTables.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserBidirectionalTables.java new file mode 100644 index 0000000..1c6eef1 --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserBidirectionalTables.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.util.List; + +final class ParserBidirectionalTables { + + private ParserBidirectionalTables() { + throw new AssertionError(); + } + + public static List> getBidirectionalPropertyRorAL() { + return ParserUtil.parseToListArrayInt("/rfcs/d1.txt"); + } + + public static List> getBidirectionalPropertyL() { + return ParserUtil.parseToListArrayInt("/rfcs/d2.txt"); + } +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserMappingTables.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserMappingTables.java new file mode 100644 index 0000000..1b456b8 --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserMappingTables.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +final class ParserMappingTables { + + private static final Pattern LINE_PATTERN = Pattern.compile("([^;]*);([^;]*);[^;]*"); + private static final Pattern CODE_POINTS_PATTERN = Pattern.compile("\\s*([0-9A-F]+)"); + + private ParserMappingTables() { + throw new AssertionError(); + } + + public static List getMapToNothing() { + return ParserUtil.parseToListInteger("/rfcs/b1.txt", LINE_PATTERN); + } + + public static Map> getMapUsedWithNfkc() { + return ParserUtil.parseToMapListInteger("/rfcs/b2.txt", LINE_PATTERN, CODE_POINTS_PATTERN); + } + + public static Map> getMapUsedWithNoNormalization() { + return ParserUtil.parseToMapListInteger("/rfcs/b3.txt", LINE_PATTERN, CODE_POINTS_PATTERN); + } +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserProhibitionTables.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserProhibitionTables.java new file mode 100644 index 0000000..a04b732 --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserProhibitionTables.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.util.List; +import java.util.regex.Pattern; + +final class ParserProhibitionTables { + + private static final Pattern PROHIBITION_PATTERN = Pattern.compile("([^;]*);[^;]*"); + + private ParserProhibitionTables() { + throw new AssertionError(); + } + + public static List getAsciiSpace() { + return ParserUtil.parseToListInteger("/rfcs/c1.1.txt", PROHIBITION_PATTERN); + } + + public static List getNonAsciiSpace() { + return ParserUtil.parseToListInteger("/rfcs/c1.2.txt", PROHIBITION_PATTERN); + } + + public static List> getAsciiControl() { + return ParserUtil.parseToListArrayInt("/rfcs/c2.1.txt", PROHIBITION_PATTERN); + } + + public static List> getNonAsciiControl() { + return ParserUtil.parseToListArrayInt("/rfcs/c2.2.txt", PROHIBITION_PATTERN); + } + + public static List> getPrivateUse() { + return ParserUtil.parseToListArrayInt("/rfcs/c3.txt", PROHIBITION_PATTERN); + } + + public static List> getNonCharacterCodePoints() { + return ParserUtil.parseToListArrayInt("/rfcs/c4.txt", PROHIBITION_PATTERN); + } + + public static List> getSurrogateCodes() { + return ParserUtil.parseToListArrayInt("/rfcs/c5.txt", PROHIBITION_PATTERN); + } + + public static List> getInappropriatePlainText() { + return ParserUtil.parseToListArrayInt("/rfcs/c6.txt", PROHIBITION_PATTERN); + } + + public static List> getInappropriateCanonicalRepresentation() { + return ParserUtil.parseToListArrayInt("/rfcs/c7.txt", PROHIBITION_PATTERN); + } + + public static List> getChangeDisplayProperties() { + return ParserUtil.parseToListArrayInt("/rfcs/c8.txt", PROHIBITION_PATTERN); + } + + public static List> getTaggingCharacters() { + return ParserUtil.parseToListArrayInt("/rfcs/c9.txt", PROHIBITION_PATTERN); + } + +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUnicodeRepertoires.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUnicodeRepertoires.java new file mode 100644 index 0000000..d43971b --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUnicodeRepertoires.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.util.List; + +final class ParserUnicodeRepertoires { + + private ParserUnicodeRepertoires() { + throw new AssertionError(); + } + + public static List> getUnassignedCodePoints() { + return ParserUtil.parseToListArrayInt("/rfcs/a1.txt"); + } +} diff --git a/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUtil.java b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUtil.java new file mode 100644 index 0000000..7f83712 --- /dev/null +++ b/codegen/src/main/java/com/ongres/stringprep/codegen/parsers/ParserUtil.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep.codegen.parsers; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +final class ParserUtil { + + private static final Pattern SPACE_PATTERN = Pattern.compile("\\s"); + + private ParserUtil() { + throw new AssertionError(); + } + + /** + * Parse a file with hexadecimal to a list of integers. + * + * @param file with the RFC file to parse + * @param pattern of the lines + * @return list of integers + */ + public static List parseToListInteger(String file, Pattern pattern) { + InputStream inputStream = ParserUtil.class.getResourceAsStream(file); + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line = null; + List codePoints = new ArrayList<>(); + while (null != (line = bufferedReader.readLine())) { + Matcher matcherLine = pattern.matcher(line); + if (matcherLine.matches()) { + String mappedFrom = SPACE_PATTERN.matcher(matcherLine.group(1)).replaceAll(""); + codePoints.add("0x" + mappedFrom); + } + } + return Collections.unmodifiableList(codePoints); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Parse a file with mappings to a map of list of integers. + * + * @param file with THE RFC file to parse + * @param patternLine pattern of the lines + * @param mapTo pattern of the conversion + * @return map of list of integers + */ + public static Map> parseToMapListInteger(String file, Pattern patternLine, + Pattern mapTo) { + InputStream inputStream = ParserUtil.class.getResourceAsStream(file); + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line = null; + Map> mapWithNoNormalization = new HashMap<>(); + while (null != (line = bufferedReader.readLine())) { + Matcher matcherLine = patternLine.matcher(line); + if (matcherLine.matches()) { + List codePoints = new ArrayList<>(); + String mappedFrom = matcherLine.group(1); + String mappedTo = matcherLine.group(2); + Matcher matcherCodePoints = mapTo.matcher(mappedTo); + while (matcherCodePoints.find()) { + codePoints.add("0x" + matcherCodePoints.group(1)); + } + String mapped = SPACE_PATTERN.matcher(mappedFrom).replaceAll(""); + mapWithNoNormalization.put("0x" + mapped, codePoints); + } + } + return Collections.unmodifiableMap(mapWithNoNormalization); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Parse a file with ranges of hexadecimal to a list of list of integers. + * + * @param file with the RFC file to parse + * @return list of list of integers + */ + public static List> parseToListArrayInt(String file) { + return parseToListArrayInt(file, null); + } + + /** + * Parse a file with ranges of hexadecimal to a list of list of integers. + * + * @param file with the RFC file to parse + * @param pattern of the lines + * @return list of list of integers + */ + public static List> parseToListArrayInt(String file, Pattern pattern) { + InputStream inputStream = ParserUtil.class.getResourceAsStream(file); + try (BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line = null; + List> codePoints = new ArrayList<>(); + if (null != pattern) { + while (null != (line = bufferedReader.readLine())) { + Matcher matcherLine = pattern.matcher(line); + if (matcherLine.matches()) { + fillList(codePoints, SPACE_PATTERN.matcher(matcherLine.group(1)).replaceAll("")); + } + } + } else { + while (null != (line = bufferedReader.readLine())) { + fillList(codePoints, SPACE_PATTERN.matcher(line).replaceAll("")); + } + } + return Collections.unmodifiableList(codePoints); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void fillList(List> codePoints, String value) { + List characters = new ArrayList<>(); + if (value.contains("-")) { + int separator = value.indexOf('-'); + characters.add("0x" + value.substring(0, separator)); + characters.add("0x" + value.substring(separator + 1)); + } else { + characters.add("0x" + value); + characters.add("0x" + value); + } + codePoints.add(characters); + } + +} diff --git a/codegenerator/src/main/resources/rfcs/a1 b/codegen/src/main/resources/rfcs/a1.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/a1 rename to codegen/src/main/resources/rfcs/a1.txt diff --git a/codegenerator/src/main/resources/rfcs/b1 b/codegen/src/main/resources/rfcs/b1.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/b1 rename to codegen/src/main/resources/rfcs/b1.txt diff --git a/codegenerator/src/main/resources/rfcs/b2 b/codegen/src/main/resources/rfcs/b2.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/b2 rename to codegen/src/main/resources/rfcs/b2.txt diff --git a/codegenerator/src/main/resources/rfcs/b3 b/codegen/src/main/resources/rfcs/b3.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/b3 rename to codegen/src/main/resources/rfcs/b3.txt diff --git a/codegenerator/src/main/resources/rfcs/c1.1 b/codegen/src/main/resources/rfcs/c1.1.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c1.1 rename to codegen/src/main/resources/rfcs/c1.1.txt diff --git a/codegenerator/src/main/resources/rfcs/c1.2 b/codegen/src/main/resources/rfcs/c1.2.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c1.2 rename to codegen/src/main/resources/rfcs/c1.2.txt diff --git a/codegenerator/src/main/resources/rfcs/c2.1 b/codegen/src/main/resources/rfcs/c2.1.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c2.1 rename to codegen/src/main/resources/rfcs/c2.1.txt diff --git a/codegenerator/src/main/resources/rfcs/c2.2 b/codegen/src/main/resources/rfcs/c2.2.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c2.2 rename to codegen/src/main/resources/rfcs/c2.2.txt diff --git a/codegenerator/src/main/resources/rfcs/c3 b/codegen/src/main/resources/rfcs/c3.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c3 rename to codegen/src/main/resources/rfcs/c3.txt diff --git a/codegenerator/src/main/resources/rfcs/c4 b/codegen/src/main/resources/rfcs/c4.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c4 rename to codegen/src/main/resources/rfcs/c4.txt diff --git a/codegenerator/src/main/resources/rfcs/c5 b/codegen/src/main/resources/rfcs/c5.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c5 rename to codegen/src/main/resources/rfcs/c5.txt diff --git a/codegenerator/src/main/resources/rfcs/c6 b/codegen/src/main/resources/rfcs/c6.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c6 rename to codegen/src/main/resources/rfcs/c6.txt diff --git a/codegenerator/src/main/resources/rfcs/c7 b/codegen/src/main/resources/rfcs/c7.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c7 rename to codegen/src/main/resources/rfcs/c7.txt diff --git a/codegenerator/src/main/resources/rfcs/c8 b/codegen/src/main/resources/rfcs/c8.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c8 rename to codegen/src/main/resources/rfcs/c8.txt diff --git a/codegenerator/src/main/resources/rfcs/c9 b/codegen/src/main/resources/rfcs/c9.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/c9 rename to codegen/src/main/resources/rfcs/c9.txt diff --git a/codegenerator/src/main/resources/rfcs/d1 b/codegen/src/main/resources/rfcs/d1.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/d1 rename to codegen/src/main/resources/rfcs/d1.txt diff --git a/codegenerator/src/main/resources/rfcs/d2 b/codegen/src/main/resources/rfcs/d2.txt similarity index 100% rename from codegenerator/src/main/resources/rfcs/d2 rename to codegen/src/main/resources/rfcs/d2.txt diff --git a/codegen/src/main/resources/templates/StringPrepTables.vm b/codegen/src/main/resources/templates/StringPrepTables.vm new file mode 100644 index 0000000..069b497 --- /dev/null +++ b/codegen/src/main/resources/templates/StringPrepTables.vm @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep; + +// AUTO-GENERATED FILE - DO NOT EDIT! + +/** + * Expose tables parsed from the StringPrep RFC-3454. + */ +public final class Tables { + + private Tables() { + throw new AssertionError(); + } + + /** + * Unassigned code points in Unicode 3.2. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Unassigned code points in Unicode 3.2". + * @see RFC 3454, Appendix A.1 + */ + public static boolean unassignedCodePoints(int codePoint) { + return #foreach( $unassignedCodePoints in $parser.getUnassignedCodePoints() ) +#if( $unassignedCodePoints.get(0) == $unassignedCodePoints.get(1) ) +codePoint == $unassignedCodePoints.get(0) +#else +(codePoint >= $unassignedCodePoints.get(0) && codePoint <= $unassignedCodePoints.get(1)) +#end +#if($foreach.hasNext) || #end#end + ; + } + + /** + * Commonly mapped to nothing. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Commonly mapped to nothing". + * @see RFC 3454, Appendix B.1 + */ + public static boolean mapToNothing(int codePoint) { + return #foreach( $mapToNothing in $parser.getMapToNothing() ) +codePoint == $mapToNothing +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Mapping for case-folding used with NFKC. + * + * @param codePoint the character (Unicode code point) to be mapped. + * @return Case-folding used with NFKC for the given {@code codePoint}. + * @see RFC 3454, Appendix B.2 + */ + public static int[] mapWithNfkc(int codePoint) { +#set ($mapNfkc = $parser.getMapUsedWithNfkc()) + switch (codePoint) { +#foreach($mapUsedWithNfkc in $mapNfkc.keySet()) + case $mapUsedWithNfkc: +#set ($valuesNfkc = $mapNfkc.get($mapUsedWithNfkc) ) + return new int[] {#foreach($value in $valuesNfkc)$value#if($foreach.hasNext), #end#end}; +#end + default: + return new int[] {codePoint}; + } + } + + /** + * Mapping for case-folding used with no normalization. + * + * @param codePoint the character (Unicode code point) to be mapped. + * @return Case-folding used with no normalization for the given {@code codePoint}. + * @see RFC 3454, Appendix B.3 + */ + public static int[] mapWithoutNormalization(int codePoint) { +#set ( $mapNormal = $parser.getMapUsedWithNoNormalization() ) + switch (codePoint) { +#foreach($mapUsedWithNoNormalization in $mapNormal.keySet() ) + case $mapUsedWithNoNormalization: +#set ($valuesNormal = $mapNormal.get($mapUsedWithNoNormalization)) + return new int[] {#foreach($value in $valuesNormal)$value#if($foreach.hasNext), #end#end}; +#end + default: + return new int[] {codePoint}; + } + } + + /** + * ASCII space characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "ASCII space characters". + * @see RFC 3454, Appendix C.1.1 + */ + public static boolean prohibitionAsciiSpace(int codePoint) { + return #foreach( $asciiSpace in $parser.getAsciiSpace() ) +codePoint == $asciiSpace +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Non-ASCII space characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-ASCII space characters". + * @see RFC 3454, Appendix C.1.2 + */ + public static boolean prohibitionNonAsciiSpace(int codePoint) { + return #foreach( $nonAsciiSpace in $parser.getNonAsciiSpace() ) +codePoint == $nonAsciiSpace +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * ASCII control characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "ASCII control characters". + * @see RFC 3454, Appendix C.2.1 + */ + public static boolean prohibitionAsciiControl(int codePoint) { + return #foreach( $asciiControl in $parser.getAsciiControl() ) +#if( $asciiControl.get(0) == $asciiControl.get(1) ) +codePoint == $asciiControl.get(0) +#else +(codePoint >= $asciiControl.get(0) && codePoint <= $asciiControl.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Non-ASCII control characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-ASCII control characters". + * @see RFC 3454, Appendix C.2.2 + */ + public static boolean prohibitionNonAsciiControl(int codePoint) { + return #foreach( $nonAsciiControl in $parser.getNonAsciiControl() ) +#if( $nonAsciiControl.get(0) == $nonAsciiControl.get(1) ) +codePoint == $nonAsciiControl.get(0) +#else +(codePoint >= $nonAsciiControl.get(0) && codePoint <= $nonAsciiControl.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Private use. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Private use". + * @see RFC 3454, Appendix C.3 + */ + public static boolean prohibitionPrivateUse(int codePoint) { + return #foreach( $privateUse in $parser.getPrivateUse() ) +#if( $privateUse.get(0) == $privateUse.get(1) ) +codePoint == $privateUse.get(0) +#else +(codePoint >= $privateUse.get(0) && codePoint <= $privateUse.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Non-character code points. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-character code points". + * @see RFC 3454, Appendix C.4 + */ + public static boolean prohibitionNonCharacterCodePoints(int codePoint) { + return #foreach( $nonCharacterCodePoints in $parser.getNonCharacterCodePoints() ) +#if( $nonCharacterCodePoints.get(0) == $nonCharacterCodePoints.get(1) ) +codePoint == $nonCharacterCodePoints.get(0) +#else +(codePoint >= $nonCharacterCodePoints.get(0) && codePoint <= $nonCharacterCodePoints.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Surrogate codes. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Surrogate codes". + * @see RFC 3454, Appendix C.5 + */ + public static boolean prohibitionSurrogateCodes(int codePoint) { + return #foreach( $surrogateCodes in $parser.getSurrogateCodes() ) +#if( $surrogateCodes.get(0) == $surrogateCodes.get(1) ) +codePoint == $surrogateCodes.get(0) +#else +(codePoint >= $surrogateCodes.get(0) && codePoint <= $surrogateCodes.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Inappropriate for plain text. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Inappropriate for plain text". + * @see RFC 3454, Appendix C.6 + */ + public static boolean prohibitionInappropriatePlainText(int codePoint) { + return #foreach( $inappropriatePlainText in $parser.getInappropriatePlainText() ) +#if( $inappropriatePlainText.get(0) == $inappropriatePlainText.get(1) ) +codePoint == $inappropriatePlainText.get(0) +#else +(codePoint >= $inappropriatePlainText.get(0) && codePoint <= $inappropriatePlainText.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Inappropriate for canonical representation. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Inappropriate for canonical representation". + * @see RFC 3454, Appendix C.7 + */ + public static boolean prohibitionInappropriateCanonicalRepresentation(int codePoint) { + return #foreach( $inappropriateCanonicalRepresentation in $parser.getInappropriateCanonicalRepresentation() ) +#if( $inappropriateCanonicalRepresentation.get(0) == $inappropriateCanonicalRepresentation.get(1) ) +codePoint == $inappropriateCanonicalRepresentation.get(0) +#else +(codePoint >= $inappropriateCanonicalRepresentation.get(0) && codePoint <= $inappropriateCanonicalRepresentation.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Change display properties or are deprecated. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Change display properties or are deprecated". + * @see RFC 3454, Appendix C.8 + */ + public static boolean prohibitionChangeDisplayProperties(int codePoint) { + return #foreach( $changeDisplayProperties in $parser.getChangeDisplayProperties() ) +#if( $changeDisplayProperties.get(0) == $changeDisplayProperties.get(1) ) +codePoint == $changeDisplayProperties.get(0) +#else +(codePoint >= $changeDisplayProperties.get(0) && codePoint <= $changeDisplayProperties.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Tagging characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Tagging characters". + * @see RFC 3454, Appendix C.9 + */ + public static boolean prohibitionTaggingCharacters(int codePoint) { + return #foreach( $taggingCharacters in $parser.getTaggingCharacters() ) +#if( $taggingCharacters.get(0) == $taggingCharacters.get(1) ) +codePoint == $taggingCharacters.get(0) +#else +(codePoint >= $taggingCharacters.get(0) && codePoint <= $taggingCharacters.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Characters with bidirectional property "R" or "AL". + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Characters with bidirectional property R or AL". + * @see RFC 3454, Appendix D.1 + */ + public static boolean bidirectionalPropertyRorAL(int codePoint) { + return #foreach( $propertyRorAL in $parser.getPropertyRorAL() ) +#if( $propertyRorAL.get(0) == $propertyRorAL.get(1) ) +codePoint == $propertyRorAL.get(0) +#else +(codePoint >= $propertyRorAL.get(0) && codePoint <= $propertyRorAL.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + + /** + * Characters with bidirectional property "L". + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Characters with bidirectional property L". + * @see RFC 3454, Appendix D.2 + */ + public static boolean bidirectionalPropertyL(int codePoint) { + return #foreach( $propertyL in $parser.getPropertyL() ) +#if( $propertyL.get(0) == $propertyL.get(1) ) +codePoint == $propertyL.get(0) +#else +(codePoint >= $propertyL.get(0) && codePoint <= $propertyL.get(1)) +#end +#if( $foreach.hasNext ) || #end#end + ; + } + +} diff --git a/thirdparty/velocity-LICENSE b/codegen/velocity-LICENSE similarity index 100% rename from thirdparty/velocity-LICENSE rename to codegen/velocity-LICENSE diff --git a/codegenerator/.gitignore b/codegenerator/.gitignore deleted file mode 100644 index b83d222..0000000 --- a/codegenerator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/codegenerator/pom.xml b/codegenerator/pom.xml deleted file mode 100644 index 5bd4d81..0000000 --- a/codegenerator/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - com.ongres.stringprep - parent - 1.1 - - codegenerator - - UTF-8 - 1.7 - - - - junit - junit - test - - - org.apache.velocity - velocity - 1.7 - - - org.apache.velocity - velocity-tools - 2.0 - - - diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/GeneratorCode.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/GeneratorCode.java deleted file mode 100644 index 844eccc..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/GeneratorCode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.StandardCharsets; - -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.app.VelocityEngine; - -@SupportedAnnotationTypes("org.code.generator.Generator") -@SupportedSourceVersion(SourceVersion.RELEASE_7) -public class GeneratorCode { - - /** - * Generate StringPrep class dynamically. - * @param args with the path used to generate StringPrep class - * @throws IOException if a RFC file can't be read - */ - public static void main(String[] args) throws IOException { - - VelocityEngine velocityEngine = new VelocityEngine(); - - velocityEngine.setProperty(Velocity.RESOURCE_LOADER, "class"); - velocityEngine.setProperty("class.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - - velocityEngine.init(); - Template template = velocityEngine.getTemplate("templates/StringPrep.vm"); - VelocityContext ctx = new VelocityContext(); - Parser parser = new Parser(); - ctx.put("parser", parser); - String path = args[0] + "/com/ongres/stringprep/StringPrep.java"; - File file = new File(path); - if (!file.getParentFile().mkdirs()) { - throw new IOException("The directory couldn't be created"); - } - Writer writer = new OutputStreamWriter(new FileOutputStream(file),StandardCharsets.UTF_8); - template.merge(ctx, writer); - writer.close(); - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/Parser.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/Parser.java deleted file mode 100644 index f66375e..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/Parser.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator; - -import com.ongres.stringprep.codegenerator.parsers.ParserBidirectionalTables; -import com.ongres.stringprep.codegenerator.parsers.ParserMappingTables; -import com.ongres.stringprep.codegenerator.parsers.ParserProhibitionTables; -import com.ongres.stringprep.codegenerator.parsers.ParserUnicodeRepertoires; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -public class Parser { - - private final List> unassignedCodePoints; - private final List mapToNothing; - private final Map> mapUsedWithNfkc; - private final Map> mapUsedWithNoNormalization; - private final List asciiSpace; - private final List nonAsciiSpace; - private final List> asciiControl; - private final List> nonAsciiControl; - private final List> privateUse; - private final List> nonCharacterCodePoints; - private final List> surrogateCodes; - private final List> inappropriatePlainText; - private final List> inappropriateCanonicalRepresentation; - private final List> changeDisplayProperties; - private final List> taggingCharacters; - private final List> propertyRorAL; - private final List> propertyL; - - /** - * Constructor of Parser class used to read all rfc files. - * @throws IOException if a RFC file can't be read - */ - public Parser() throws IOException { - unassignedCodePoints = ParserUnicodeRepertoires.parseUnassignedCodePoints(); - mapToNothing = ParserMappingTables.parseMapToNothing(); - mapUsedWithNfkc = ParserMappingTables.parseMapUsedWithNfkc(); - mapUsedWithNoNormalization = ParserMappingTables.parseMapUsedWithNoNormalization(); - asciiSpace = ParserProhibitionTables.parseAsciiSpace(); - nonAsciiSpace = ParserProhibitionTables.parseNonAsciiSpace(); - asciiControl = ParserProhibitionTables.parseAsciiControl(); - nonAsciiControl = ParserProhibitionTables.parseNonAsciiControl(); - privateUse = ParserProhibitionTables.parsePrivateUse(); - nonCharacterCodePoints = ParserProhibitionTables.parseNonCharacterCodePoints(); - surrogateCodes = ParserProhibitionTables.parseSurrogateCodes(); - inappropriatePlainText = ParserProhibitionTables.parseInappropriatePlainText(); - inappropriateCanonicalRepresentation = - ParserProhibitionTables.parseInappropriateCanonicalRepresentation(); - changeDisplayProperties = ParserProhibitionTables.parseChangeDisplayProperties(); - taggingCharacters = ParserProhibitionTables.parseTaggingCharacters(); - propertyRorAL = ParserBidirectionalTables.parseBidirectionalPropertyRorAL(); - propertyL = ParserBidirectionalTables.parseBidirectionalPropertyL(); - } - - public List> getUnassignedCodePoints() { - return unassignedCodePoints; - } - - public List getMapToNothing() { - return mapToNothing; - } - - public Map> getMapUsedWithNfkc() { - return mapUsedWithNfkc; - } - - public Map> getMapUsedWithNoNormalization() { - return mapUsedWithNoNormalization; - } - - public List getAsciiSpace() { - return asciiSpace; - } - - public List getNonAsciiSpace() { - return nonAsciiSpace; - } - - public List> getAsciiControl() { - return asciiControl; - } - - public List> getNonAsciiControl() { - return nonAsciiControl; - } - - public List> getPrivateUse() { - return privateUse; - } - - public List> getNonCharacterCodePoints() { - return nonCharacterCodePoints; - } - - public List> getSurrogateCodes() { - return surrogateCodes; - } - - public List> getInappropriatePlainText() { - return inappropriatePlainText; - } - - public List> getInappropriateCanonicalRepresentation() { - return inappropriateCanonicalRepresentation; - } - - public List> getChangeDisplayProperties() { - return changeDisplayProperties; - } - - public List> getTaggingCharacters() { - return taggingCharacters; - } - - public List> getPropertyRorAL() { - return propertyRorAL; - } - - public List> getPropertyL() { - return propertyL; - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserBidirectionalTables.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserBidirectionalTables.java deleted file mode 100644 index 9f13f5c..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserBidirectionalTables.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator.parsers; - -import java.io.IOException; -import java.util.List; - -public class ParserBidirectionalTables { - - private ParserBidirectionalTables() { - } - - public static List> parseBidirectionalPropertyRorAL() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/d1"); - } - - public static List> parseBidirectionalPropertyL() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/d2"); - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserMappingTables.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserMappingTables.java deleted file mode 100644 index 06cde48..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserMappingTables.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator.parsers; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -public class ParserMappingTables { - - private ParserMappingTables() { - } - - private static final Pattern LINE_PATTERN = Pattern.compile("([^;]*);([^;]*);[^;]*"); - private static final Pattern CODE_POINTS_PATTERN = Pattern.compile("\\s*([0-9A-F]+)"); - - public static List parseMapToNothing() throws IOException { - return new ParserUtil().parseToListInteger("/rfcs/b1", LINE_PATTERN); - } - - public static Map> parseMapUsedWithNfkc() throws IOException { - return new ParserUtil().parseToMapListInteger("/rfcs/b2", LINE_PATTERN, CODE_POINTS_PATTERN); - } - - public static Map> parseMapUsedWithNoNormalization() throws IOException { - return new ParserUtil().parseToMapListInteger("/rfcs/b3", LINE_PATTERN, CODE_POINTS_PATTERN); - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserProhibitionTables.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserProhibitionTables.java deleted file mode 100644 index 390d63e..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserProhibitionTables.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator.parsers; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -public class ParserProhibitionTables { - - private ParserProhibitionTables() { - } - - private static final Pattern PROHIBITION_PATTERN = Pattern.compile("([^;]*);[^;]*"); - - public static List parseAsciiSpace() throws IOException { - return new ParserUtil().parseToListInteger("/rfcs/c1.1", PROHIBITION_PATTERN); - } - - public static List parseNonAsciiSpace() throws IOException { - return new ParserUtil().parseToListInteger("/rfcs/c1.2", PROHIBITION_PATTERN); - } - - public static List> parseAsciiControl() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c2.1", PROHIBITION_PATTERN); - } - - public static List> parseNonAsciiControl() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c2.2", PROHIBITION_PATTERN); - } - - public static List> parsePrivateUse() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c3", PROHIBITION_PATTERN); - } - - public static List> parseNonCharacterCodePoints() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c4", PROHIBITION_PATTERN); - } - - public static List> parseSurrogateCodes() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c5", PROHIBITION_PATTERN); - } - - public static List> parseInappropriatePlainText() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c6", PROHIBITION_PATTERN); - } - - public static List> parseInappropriateCanonicalRepresentation() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c7", PROHIBITION_PATTERN); - } - - public static List> parseChangeDisplayProperties() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c8", PROHIBITION_PATTERN); - } - - public static List> parseTaggingCharacters() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/c9", PROHIBITION_PATTERN); - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUnicodeRepertoires.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUnicodeRepertoires.java deleted file mode 100644 index 0d0182c..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUnicodeRepertoires.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator.parsers; - -import java.io.IOException; -import java.util.List; - -public class ParserUnicodeRepertoires { - - private ParserUnicodeRepertoires() { - } - - public static List> parseUnassignedCodePoints() throws IOException { - return new ParserUtil().parseToListArrayInt("/rfcs/a1"); - } -} diff --git a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUtil.java b/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUtil.java deleted file mode 100644 index 5e3fc72..0000000 --- a/codegenerator/src/main/java/com/ongres/stringprep/codegenerator/parsers/ParserUtil.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep.codegenerator.parsers; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ParserUtil { - - /** - * Parse a file with hexadecimal to a list of integers. - * @param file with the RFC file to parse - * @param pattern of the lines - * @return list of integers - * @throws IOException if a RFC file can't be read - */ - public List parseToListInteger( - String file, Pattern pattern) throws NumberFormatException, IOException { - InputStream inputStream = ParserUtil.class.getResourceAsStream(file); - BufferedReader bufferedReader = new BufferedReader( - new InputStreamReader(inputStream, Charset.defaultCharset())); - String line = null; - List codePoints = new ArrayList<>(); - while (null != (line = bufferedReader.readLine())) { - Matcher matcherLine = pattern.matcher(line); - if (matcherLine.matches()) { - String mappedFrom = matcherLine.group(1).replaceAll("\\s",""); - codePoints.add(Integer.parseInt(mappedFrom, 16)); - } - } - return codePoints; - } - - /** - * Parse a file with mappings to a map of list of integers. - * @param file with THE RFC file to parse - * @param patternLine pattern of the lines - * @param mapTo pattern of the conversion - * @return map of list of integers - * @throws IOException if a RFC file can't be read - */ - public Map> parseToMapListInteger( - String file, Pattern patternLine, Pattern mapTo) throws IOException { - InputStream inputStream = ParserUtil.class.getResourceAsStream(file); - BufferedReader bufferedReader = new BufferedReader( - new InputStreamReader(inputStream, Charset.defaultCharset())); - String line = null; - Map> mapWithNoNormalization = new HashMap<>(); - while (null != (line = bufferedReader.readLine())) { - List codePoints = new ArrayList<>(); - Matcher matcherLine = patternLine.matcher(line); - if (matcherLine.matches()) { - String mappedFrom = matcherLine.group(1); - String mappedTo = matcherLine.group(2); - Matcher matcherCodePoints = mapTo.matcher(mappedTo); - while (matcherCodePoints.find()) { - codePoints.add(Integer.parseInt(matcherCodePoints.group(1), 16)); - } - String mapped = mappedFrom.replaceAll("\\s", ""); - mapWithNoNormalization.put(Integer.parseInt(mapped, 16), codePoints); - } - } - return mapWithNoNormalization; - } - - /** - * Parse a file with ranges of hexadecimal to a list of list of integers. - * @param file with the RFC file to parse - * @return list of list of integers - * @throws IOException if a RFC file can't be read - */ - public List> parseToListArrayInt( - String file) throws NumberFormatException, IOException { - return parseToListArrayInt(file, null); - } - - /** - * Parse a file with ranges of hexadecimal to a list of list of integers. - * @param file with the RFC file to parse - * @param pattern of the lines - * @return list of list of integers - * @throws IOException if a RFC file can't be read - */ - public List> parseToListArrayInt( - String file, Pattern pattern) throws NumberFormatException, IOException { - InputStream inputStream = ParserUtil.class.getResourceAsStream(file); - BufferedReader bufferedReader = new BufferedReader( - new InputStreamReader(inputStream, Charset.defaultCharset())); - String line = null; - List> codePoints = new ArrayList<>(); - if (null != pattern) { - while (null != (line = bufferedReader.readLine())) { - Matcher matcherLine = pattern.matcher(line); - if (matcherLine.matches()) { - fillList(codePoints, matcherLine.group(1).replaceAll("\\s", "")); - } - } - } else { - while (null != (line = bufferedReader.readLine())) { - fillList(codePoints, line.replaceAll("\\s", "")); - } - } - return codePoints; - } - - private void fillList(List> codePoints,String value) { - List characters = new ArrayList<>(); - if (value.contains("-")) { - int separator = value.indexOf('-'); - characters.add(Integer.parseInt(value.substring(0, separator), 16)); - characters.add(Integer.parseInt(value.substring(separator + 1), 16)); - } else { - characters.add(Integer.parseInt(value, 16)); - characters.add(Integer.parseInt(value, 16)); - } - codePoints.add(characters); - } - -} diff --git a/codegenerator/src/main/resources/templates/StringPrep.vm b/codegenerator/src/main/resources/templates/StringPrep.vm deleted file mode 100644 index 1f04e03..0000000 --- a/codegenerator/src/main/resources/templates/StringPrep.vm +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep; - -import java.io.IOException; -import java.util.List; - -public class StringPrep { - - public static boolean unassignedCodePoints(int codepoint) { - return - #foreach( $unassignedCodePoints in $parser.getUnassignedCodePoints() ) #if( $unassignedCodePoints.get(0) == $unassignedCodePoints.get(1) ) codepoint == $unassignedCodePoints.get(0) #else codepoint >= $unassignedCodePoints.get(0) && codepoint <= $unassignedCodePoints.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean mapToNothing(int codepoint) { - return - #foreach( $mapToNothing in $parser.getMapToNothing() ) codepoint == $mapToNothing #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static int[] mapUsedWithNfkc(int codepoint) { - #set ( $mapNfkc = $parser.getMapUsedWithNfkc() ) - switch(codepoint) { -#foreach( $mapUsedWithNfkc in $mapNfkc.keySet() ) - case( $mapUsedWithNfkc ): -#set ( $valuesNfkc = $mapNfkc.get($mapUsedWithNfkc) ) - return new int[]{#foreach($value in $valuesNfkc) $value #if($foreach.hasNext),#end#end}; -#end - default: - return new int[] { codepoint}; - } - } - - public static int[] mapUsedWithNoNormalization(int codepoint) { - #set ( $mapNormal = $parser.getMapUsedWithNoNormalization() ) - switch(codepoint) { -#foreach( $mapUsedWithNoNormalization in $mapNormal.keySet() ) - case( $mapUsedWithNoNormalization ): -#set ( $valuesNormal = $mapNormal.get($mapUsedWithNoNormalization) ) - return new int[]{#foreach($value in $valuesNormal) $value #if($foreach.hasNext),#end#end}; -#end - default: - return new int[] { codepoint}; - } - } - - public static boolean prohibitionAsciiSpace(int codepoint) { - return - #foreach( $asciiSpace in $parser.getAsciiSpace() ) codepoint == $asciiSpace #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionNonAsciiSpace(int codepoint) { - return - #foreach( $nonAsciiSpace in $parser.getNonAsciiSpace() ) codepoint == $nonAsciiSpace #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionAsciiControl(int codepoint) { - return - #foreach( $asciiControl in $parser.getAsciiControl() ) #if( $asciiControl.get(0) == $asciiControl.get(1) ) codepoint == $asciiControl.get(0) #else codepoint >= $asciiControl.get(0) && codepoint <= $asciiControl.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionNonAsciiControl(int codepoint) { - return - #foreach( $nonAsciiControl in $parser.getNonAsciiControl() ) #if( $nonAsciiControl.get(0) == $nonAsciiControl.get(1) ) codepoint == $nonAsciiControl.get(0) #else codepoint >= $nonAsciiControl.get(0) && codepoint <= $nonAsciiControl.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionPrivateUse(int codepoint) { - return - #foreach( $privateUse in $parser.getPrivateUse() ) #if( $privateUse.get(0) == $privateUse.get(1) ) codepoint == $privateUse.get(0) #else codepoint >= $privateUse.get(0) && codepoint <= $privateUse.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionNonCharacterCodePoints(int codepoint) { - return - #foreach( $nonCharacterCodePoints in $parser.getNonCharacterCodePoints() ) #if( $nonCharacterCodePoints.get(0) == $nonCharacterCodePoints.get(1) ) codepoint == $nonCharacterCodePoints.get(0) #else codepoint >= $nonCharacterCodePoints.get(0) && codepoint <= $nonCharacterCodePoints.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionSurrogateCodes(int codepoint) { - return - #foreach( $surrogateCodes in $parser.getSurrogateCodes() ) #if( $surrogateCodes.get(0) == $surrogateCodes.get(1) ) codepoint == $surrogateCodes.get(0) #else codepoint >= $surrogateCodes.get(0) && codepoint <= $surrogateCodes.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionInappropriatePlainText(int codepoint) { - return - #foreach( $inappropriatePlainText in $parser.getInappropriatePlainText() ) #if( $inappropriatePlainText.get(0) == $inappropriatePlainText.get(1) ) codepoint == $inappropriatePlainText.get(0) #else codepoint >= $inappropriatePlainText.get(0) && codepoint <= $inappropriatePlainText.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionInappropriateCanonicalRepresentation(int codepoint) { - return - #foreach( $inappropriateCanonicalRepresentation in $parser.getInappropriateCanonicalRepresentation() ) #if( $inappropriateCanonicalRepresentation.get(0) == $inappropriateCanonicalRepresentation.get(1) ) codepoint == $inappropriateCanonicalRepresentation.get(0) #else codepoint >= $inappropriateCanonicalRepresentation.get(0) && codepoint <= $inappropriateCanonicalRepresentation.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionChangeDisplayProperties(int codepoint) { - return - #foreach( $changeDisplayProperties in $parser.getChangeDisplayProperties() ) #if( $changeDisplayProperties.get(0) == $changeDisplayProperties.get(1) ) codepoint == $changeDisplayProperties.get(0) #else codepoint >= $changeDisplayProperties.get(0) && codepoint <= $changeDisplayProperties.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean prohibitionTaggingCharacters(int codepoint) { - return - #foreach( $taggingCharacters in $parser.getTaggingCharacters() ) #if( $taggingCharacters.get(0) == $taggingCharacters.get(1) ) codepoint == $taggingCharacters.get(0) #else codepoint >= $taggingCharacters.get(0) && codepoint <= $taggingCharacters.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean bidirectionalPropertyRorAL(int codepoint) { - return - #foreach( $propertyRorAL in $parser.getPropertyRorAL() ) #if( $propertyRorAL.get(0) == $propertyRorAL.get(1) ) codepoint == $propertyRorAL.get(0) #else codepoint >= $propertyRorAL.get(0) && codepoint <= $propertyRorAL.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean bidirectionalPropertyL(int codepoint) { - return - #foreach( $propertyL in $parser.getPropertyL() ) #if( $propertyL.get(0) == $propertyL.get(1) ) codepoint == $propertyL.get(0) #else codepoint >= $propertyL.get(0) && codepoint <= $propertyL.get(1) #end #if( $foreach.hasNext )|| -#end - #end - - ; - } - - public static boolean bidirectional(List value) throws IllegalArgumentException { - boolean containPropertyRorAL = false; - boolean firstCharacterPropertyRorAL = false; - boolean lastCharacterPropertyRorAL = false; - boolean containPropertyL = false; - for (int i=0; i + + 4.0.0 + + + com.ongres.stringprep + stringprep-parent + 2.1 + ../parent/pom.xml + + + coverage-report + pom + + JaCoCo Coverage Report + + + true + true + + + + + com.ongres.stringprep + stringprep + ${project.version} + + + com.ongres.stringprep + saslprep + ${project.version} + + + com.ongres.stringprep + nameprep + ${project.version} + + + + + + + org.jacoco + jacoco-maven-plugin + + + com/ongres/stringprep/Tables* + META-INF/versions/** + + + + + report-aggregate + + report-aggregate + + verify + + + + + + diff --git a/debian/changelog b/debian/changelog index 85028f3..d327390 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,23 @@ +libstringprep-java (2.1-1) unstable; urgency=medium + + * Team upload. + * New upstream release + - Updated the Maven build + - libstringprep-java 2.1 breaks libscram-java (<< 2.0) + * Enabled the unit tests + * Standards-Version updated to 4.7.0 + + -- Emmanuel Bourg Mon, 10 Feb 2025 09:22:06 +0100 + +libstringprep-java (1.1-3) unstable; urgency=medium + + * Team upload. + * Address FTBFS with build-helper-maven-plugin 3.3.0 (Closes: #1022277) + * Bump Standards-Version to 4.6.1 + * Set Rules-Requires-Root: no in debian/control + + -- tony mancill Tue, 25 Oct 2022 22:04:02 -0700 + libstringprep-java (1.1-2) unstable; urgency=medium * Source-only upload. diff --git a/debian/control b/debian/control index d2c7532..53ec920 100644 --- a/debian/control +++ b/debian/control @@ -7,18 +7,16 @@ Uploaders: Build-Depends: debhelper-compat (= 13), default-jdk, - junit4, - libbuild-helper-maven-plugin-java, + junit5, libmaven-exec-plugin-java, - libmaven-javadoc-plugin-java, - libmaven-source-plugin-java, maven-debian-helper (>= 2.1), Build-Depends-Indep: default-jdk-doc, -Standards-Version: 4.5.0 +Standards-Version: 4.7.0 Vcs-Git: https://salsa.debian.org/java-team/libstringprep-java.git Vcs-Browser: https://salsa.debian.org/java-team/libstringprep-java Homepage: https://gitlab.com/ongresinc/stringprep +Rules-Requires-Root: no Package: libstringprep-java Architecture: all @@ -26,6 +24,7 @@ Multi-Arch: foreign Depends: ${maven:Depends}, ${misc:Depends}, +Breaks: libscram-java (<< 2.0) Description: Stringprep (RFC 3454) Java implementation This project implements the RFC 3454 Preparation of Internationalized Strings ("stringprep") in pure Java. diff --git a/debian/copyright b/debian/copyright index 06f8507..732614a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -8,7 +8,8 @@ Copyright: License: 2-clause-BSD Files: debian/* -Copyright: 2021, Christoph Berg +Copyright: 2021-2022, Christoph Berg + 2022, tony mancill License: 2-clause-BSD License: 2-clause-BSD diff --git a/debian/libstringprep-java.poms b/debian/libstringprep-java.poms index 0417132..ca0d36d 100644 --- a/debian/libstringprep-java.poms +++ b/debian/libstringprep-java.poms @@ -25,4 +25,8 @@ # --site-xml=: Optional, the location for site.xml if it needs to be installed. # Empty by default. [mh_install] # -pom.xml --has-package-version +pom.xml --has-package-version +parent/pom.xml --has-package-version +stringprep/pom.xml --has-package-version +saslprep/pom.xml --has-package-version +nameprep/pom.xml --has-package-version diff --git a/debian/maven.ignoreRules b/debian/maven.ignoreRules index e69de29..6220a5a 100644 --- a/debian/maven.ignoreRules +++ b/debian/maven.ignoreRules @@ -0,0 +1,2 @@ +org.apache.maven.plugins maven-enforcer-plugin + diff --git a/debian/maven.properties b/debian/maven.properties index 3b73c63..55d6188 100644 --- a/debian/maven.properties +++ b/debian/maven.properties @@ -3,5 +3,4 @@ # maven.test.skip=true # project.build.sourceEncoding=UTF-8 -maven.test.skip=true -maven.javadoc.skip=true +maven.test.skip=false diff --git a/debian/maven.rules b/debian/maven.rules index 2ebbcdb..e69de29 100644 --- a/debian/maven.rules +++ b/debian/maven.rules @@ -1 +0,0 @@ -junit junit jar s/4\..*/4.x/ * * diff --git a/debian/rules b/debian/rules index 16b8910..2d33f6a 100755 --- a/debian/rules +++ b/debian/rules @@ -2,7 +2,3 @@ %: dh $@ - -override_dh_auto_test: - # disabled for now - # [ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0:java (generate-stringprep) on project stringprep: An exception occured while executing the Java class. The directory couldn't be created -> [Help 1] diff --git a/debian/watch b/debian/watch index cc5a8ba..3aec3c2 100644 --- a/debian/watch +++ b/debian/watch @@ -1,3 +1,3 @@ version=4 -options="uversionmangle=s/.beta/~beta/" \ -https://gitlab.com/ongresinc/stringprep/-/tags .*/stringprep-(.*)\.tar\.gz +options="searchmode=plain, uversionmangle=s/.beta/~beta/" \ +https://gitlab.com/ongresinc/stringprep/tags?sort=updated_desc -/archive/[\d.]+/stringprep-@ANY_VERSION@@ARCHIVE_EXT@ diff --git a/mvnw b/mvnw index d2f0ea3..8d937f4 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script +# Apache Maven Wrapper startup batch script, version 3.2.0 # # Required ENV vars: # ------------------ @@ -27,7 +27,6 @@ # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -36,6 +35,10 @@ if [ -z "$MAVEN_SKIP_RC" ] ; then + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi @@ -50,7 +53,7 @@ fi cygwin=false; darwin=false; mingw=false -case "`uname`" in +case "$(uname)" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true @@ -58,9 +61,9 @@ case "`uname`" in # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME else - export JAVA_HOME="/Library/Java/Home" + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi fi ;; @@ -68,68 +71,38 @@ esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + JAVA_HOME=$(java-config --jre-home) fi fi -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - 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 - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi @@ -145,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`which java`" + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi @@ -159,12 +132,9 @@ if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { - if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" @@ -180,96 +150,99 @@ find_maven_basedir() { fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done - echo "${basedir}" + printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" fi } -BASE_DIR=`find_maven_basedir "$(pwd)"` +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi + log "Couldn't find $wrapperJarPath, downloading it ..." + if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi @@ -278,33 +251,58 @@ fi # End of extension ########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd index b26ab24..c4586b5 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,15 +18,14 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script +@REM Apache Maven Wrapper startup batch script, version 3.2.0 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @REM @REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @@ -46,8 +45,8 @@ if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") @REM Execute a user defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* :skipRcPre @setlocal @@ -120,10 +119,10 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @@ -134,11 +133,11 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% + echo Downloading from: %WRAPPER_URL% ) powershell -Command "&{"^ @@ -146,7 +145,7 @@ if exist %WRAPPER_JAR% ( "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ "}" if "%MVNW_VERBOSE%" == "true" ( echo Finished downloading %WRAPPER_JAR% @@ -154,11 +153,35 @@ if exist %WRAPPER_JAR% ( ) @REM End of extension +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end @@ -168,15 +191,15 @@ set ERROR_CODE=1 :end @endlocal & set ERROR_CODE=%ERROR_CODE% -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost @REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" :skipRcPost @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause +if "%MAVEN_BATCH_PAUSE%"=="on" pause -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% -exit /B %ERROR_CODE% +cmd /C exit /B %ERROR_CODE% diff --git a/nameprep/pom.xml b/nameprep/pom.xml new file mode 100644 index 0000000..643e473 --- /dev/null +++ b/nameprep/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + + com.ongres.stringprep + stringprep-parent + 2.1 + ../parent/pom.xml + + + nameprep + Nameprep (RFC 3491) + Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN) + + + ${project.basedir}/../checks + + + + + com.ongres.stringprep + stringprep + ${project.version} + + + + + + coverage + + + + org.jacoco + jacoco-maven-plugin + + + + + + run-its + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-invoker-plugin + + + + + + diff --git a/nameprep/src/it/jpms-nameprep/invoker.properties b/nameprep/src/it/jpms-nameprep/invoker.properties new file mode 100644 index 0000000..93b7001 --- /dev/null +++ b/nameprep/src/it/jpms-nameprep/invoker.properties @@ -0,0 +1,3 @@ +# build project if JRE version is 11 or higher +invoker.java.version = 11+ +invoker.goals = test diff --git a/nameprep/src/it/jpms-nameprep/pom.xml b/nameprep/src/it/jpms-nameprep/pom.xml new file mode 100644 index 0000000..2f138a6 --- /dev/null +++ b/nameprep/src/it/jpms-nameprep/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + com.ongres.stringprep.it + jpms-nameprep + JPMS Nameprep + 2.1 + + + UTF-8 + 11 + 11 + 11 + + + + + com.ongres.stringprep + nameprep + ${project.version} + + + org.junit.jupiter + junit-jupiter + 5.10.2 + test + + + + + + + + maven-compiler-plugin + 3.13.0 + + + maven-jar-plugin + 3.3.0 + + + + + + + de.sormuras.junit + junit-platform-maven-plugin + 1.1.7 + true + + ABSOLUTE + JAVA + + + + + diff --git a/nameprep/src/it/jpms-nameprep/src/test/java/module-info.java b/nameprep/src/it/jpms-nameprep/src/test/java/module-info.java new file mode 100644 index 0000000..ed3e871 --- /dev/null +++ b/nameprep/src/it/jpms-nameprep/src/test/java/module-info.java @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +open module test.nameprep { + requires com.ongres.nameprep; + + requires transitive org.junit.jupiter.engine; + requires transitive org.junit.jupiter.api; + requires transitive org.junit.jupiter.params; +} \ No newline at end of file diff --git a/nameprep/src/it/jpms-nameprep/src/test/java/test/nameprep/NameprepTest.java b/nameprep/src/it/jpms-nameprep/src/test/java/test/nameprep/NameprepTest.java new file mode 100644 index 0000000..ef8c7cb --- /dev/null +++ b/nameprep/src/it/jpms-nameprep/src/test/java/test/nameprep/NameprepTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package test.nameprep; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.EnumSet; + +import com.ongres.nameprep.Nameprep; +import com.ongres.stringprep.Option; +import com.ongres.stringprep.Profile; +import com.ongres.stringprep.Stringprep; +import org.junit.jupiter.api.Test; + +class NameprepTest { + + @Test + void getProvider() { + assertDoesNotThrow(() -> Stringprep.getProvider("Nameprep")); + assertThrows(IllegalArgumentException.class, () -> Stringprep.getProvider("SASLprep")); + } + + @Test + void service() { + Profile service = Stringprep.getProvider("Nameprep"); + assertEquals(EnumSet.of(Option.MAP_TO_NOTHING, // [StringPrep, B.1] + Option.CASE_FOLD_NFKC, // [StringPrep, B.2] + Option.NORMALIZE_KC, // Normalization form KC + Option.FORBID_NON_ASCII_SPACES, // [StringPrep, C.1.2] + Option.FORBID_NON_ASCII_CONTROL, // [StringPrep, C.2.2] + Option.FORBID_PRIVATE_USE, // [StringPrep, C.3] + Option.FORBID_NON_CHARACTER, // [StringPrep, C.4] + Option.FORBID_SURROGATE, // [StringPrep, C.5] + Option.FORBID_INAPPROPRIATE_FOR_PLAIN_TEXT, // [StringPrep, C.6] + Option.FORBID_INAPPROPRIATE_FOR_CANON_REP, // [StringPrep, C.7] + Option.FORBID_CHANGE_DISPLAY_AND_DEPRECATED, // [StringPrep, C.8] + Option.FORBID_TAGGING, // [StringPrep, C.9] + Option.CHECK_BIDI), // Bidirectional Characters + service.profile()); + String withUnassignedChar = "\u0380"; + assertDoesNotThrow(() -> service.prepareQuery(withUnassignedChar)); + assertThrows(IllegalArgumentException.class, () -> service.prepareStored(withUnassignedChar)); + } + + @Test + void newInstance() { + // Access the exported package + Nameprep profile = new Nameprep(); + String example1 = "I\u00ADX \u2168"; + assertEquals("ix ix", profile.prepareStored(example1)); + assertEquals("ix ix", profile.prepareQuery(example1)); + } + +} diff --git a/nameprep/src/it/settings.xml b/nameprep/src/it/settings.xml new file mode 100644 index 0000000..8890c85 --- /dev/null +++ b/nameprep/src/it/settings.xml @@ -0,0 +1,35 @@ + + + + + it-repo + + true + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + diff --git a/nameprep/src/main/java/com/ongres/nameprep/Nameprep.java b/nameprep/src/main/java/com/ongres/nameprep/Nameprep.java new file mode 100644 index 0000000..7756bf2 --- /dev/null +++ b/nameprep/src/main/java/com/ongres/nameprep/Nameprep.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.nameprep; + +import java.util.EnumSet; +import java.util.Set; + +import com.ongres.stringprep.Option; +import com.ongres.stringprep.Profile; +import com.ongres.stringprep.ProfileName; + +/** + * Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN). + * + *

This document specifies processing rules that will allow users to enter internationalized + * domain names (IDNs) into applications and have the highest chance of getting the content of the + * strings correct. It is a profile of stringprep. These processing rules are only intended for + * internationalized domain names, not for arbitrary text. + */ +@ProfileName("Nameprep") +public final class Nameprep implements Profile { + + private final EnumSet

The use of simple user names and passwords in authentication and authorization is pervasive on + * the Internet. To increase the likelihood that user name and password input and comparison work in + * ways that make sense for typical users throughout the world, this document defines rules for + * preparing internationalized user names and passwords for comparison. For simplicity and + * implementation ease, a single algorithm is defined for both user names and passwords. + */ +@ProfileName("SASLprep") +public final class SASLprep implements Profile { + + private final EnumSet

Stringprep profiles can also exclude characters that should not normally appear in text that + * is used in the protocol. The profile can prevent such characters by changing the characters to be + * excluded to other characters, by removing those characters, or by causing an error if the + * characters would appear in the output. + * + * @since 2.0 + */ +public interface Profile { + + /** + * Set of options used by the profile. + * + * @return profile options. + */ + Set

A profile with {@code @ProfileName("SASLprep")} can can be obtained by calling + * {@code Stringprep.getProvider("SASLprep")}. + */ +@Documented +@Retention(RUNTIME) +@Target(TYPE) +public @interface ProfileName { + + /** + * Define the Stringprep profile name as defined by the RFC. + * + * @return profile name + */ + String value(); +} diff --git a/stringprep/src/main/java/com/ongres/stringprep/Stringprep.java b/stringprep/src/main/java/com/ongres/stringprep/Stringprep.java new file mode 100644 index 0000000..5d9b066 --- /dev/null +++ b/stringprep/src/main/java/com/ongres/stringprep/Stringprep.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep; + +import java.nio.CharBuffer; +import java.text.Normalizer; +import java.util.EnumSet; +import java.util.Locale; +import java.util.Objects; +import java.util.function.IntPredicate; + +/** + * Java implementation of StringPrep (RFC 3454). + * + * @see RFC 3454 + * @version 2.0 + */ +public final class Stringprep { + + private final Profile profile; + private final boolean mapToNothing; + private final boolean additionalMapping; + private final boolean caseFoldNfkc; + private final boolean caseFoldNoNormalization; + private final boolean normalizeKc; + private final boolean checkBidi; + private final boolean forbidAdditionalCharacters; + private final boolean forbidAsciiSpaces; + private final boolean forbidNonAsciiSpaces; + private final boolean forbidAsciiControl; + private final boolean forbidNonAsciiControl; + private final boolean forbidPrivateUse; + private final boolean forbidNonCharacter; + private final boolean forbidSurrogate; + private final boolean forbidInappropriatePlainText; + private final boolean forbidInappropriateCanonRep; + private final boolean forbidChangeDisplayDeprecated; + private final boolean forbidTagging; + private final boolean forbidUnassigned; + + /** + * Create a Stringprep instance based on a {@link Profile} {@link Option}s and the two different + * types of strings in typical protocols where internationalized strings are used: "stored + * strings" and "queries". + * + * @param profile includes the options to implement a Stringprep profile. + * @param storedStrings "stored strings" MUST NOT contain unassigned code points, "queries" MAY + * include them. + * @throws NullPointerException if {@code profile} is {@code null}. + */ + Stringprep(Profile profile, boolean storedStrings) { + Objects.requireNonNull(profile); + EnumSet

The steps for preparing strings are: + * + *

  1. Map -- For each character in the input, check if it has a mapping and, if so, replace + * it with its mapping. This is described in section 3. + * + *
  2. Normalize -- Possibly normalize the result of step 1 using Unicode normalization. This is + * described in section 4. + * + *
  3. Prohibit -- Check for any characters that are not allowed in the output. If any are found, + * return an error. This is described in section 5. + * + *
  4. Check bidi -- Possibly check for right-to-left characters, and if any are found, make sure + * that the whole string satisfies the requirements for bidirectional strings. If the string does + * not satisfy the requirements for bidirectional strings, return an error. This is described in + * section 6.
+ * + * @param string to prepare. + * + * @return The prepared string following the options of the profile. + * @throws IllegalArgumentException if there are prohibited or bidi characters depending on the + * profile used. + * @throws NullPointerException if {@code string} is {@code null}. + */ + char[] prepare(final char[] string) { + Objects.requireNonNull(string, "The string to prepare must not be null"); + if (string.length == 0) { + return string; + } + + char[] value = string.clone(); + + // 1) Map -- For each character in the input, check if it has a mapping + // and, if so, replace it with its mapping. + value = map(value); + + // 2) Normalize -- Possibly normalize the result of step 1 using Unicode + // normalization. + if (normalizeKc) { + value = Normalizer.normalize(CharBuffer.wrap(value), Normalizer.Form.NFKC).toCharArray(); + } + + boolean firstRandAlCat = Tables.bidirectionalPropertyRorAL(Character.codePointAt(value, 0)); + boolean lastRandAlCat = + Tables.bidirectionalPropertyRorAL(Character.codePointAt(value, value.length - 1)); + boolean containsRandAlCat = false; + boolean containsLcat = false; + int codePoint; + for (int i = 0; i < value.length; i += Character.charCount(codePoint)) { + codePoint = Character.codePointAt(value, i); + + // 3) Prohibit -- Check for any characters that are not allowed in the + // output. If any are found, return an error. + prohibitedOutput(codePoint); + + // 4) Check bidi -- Possibly check for right-to-left characters, and if + // any are found, make sure that the whole string satisfies the + // requirements for bidirectional strings. If the string does not + // satisfy the requirements for bidirectional strings, return an + // error. + if (checkBidi) { + // 1) The characters in section 5.8 MUST be prohibited. + checkProhibited(true, Tables::prohibitionChangeDisplayProperties, + codePoint, "Prohibited control character"); + + if (Tables.bidirectionalPropertyRorAL(codePoint)) { + containsRandAlCat = true; + } + if (Tables.bidirectionalPropertyL(codePoint)) { + containsLcat = true; + } + // 2) If a string contains any RandALCat character, + // the string MUST NOT contain any LCat character. + if (containsRandAlCat && containsLcat) { + throw new IllegalArgumentException("Prohibited string with RandALCat and LCat"); + } + // 3) If a string contains any RandALCat character, a RandALCat + // character MUST be the first character of the string, and a + // RandALCat character MUST be the last character of the string. + if (containsRandAlCat && !(firstRandAlCat && lastRandAlCat)) { + throw new IllegalArgumentException( + "RandALCat character is not the first and the last character"); + } + } + } + + return value; + } + + private char[] map(char[] string) { + final StringBuilder mapping = new StringBuilder(string.length); + for (int codePoint, i = 0; i < string.length; i += Character.charCount(codePoint)) { + codePoint = Character.codePointAt(string, i); + + if (mapToNothing && Tables.mapToNothing(codePoint)) { // NOPMD + // The following characters are simply deleted from the input (that is, + // they are mapped to nothing) because their presence or absence in + // protocol identifiers should not make two strings different. They are + // listed in Table B.1. + } else if (normalizeKc && caseFoldNfkc) { + // appendix B.2 is for profiles that also use Unicode + // normalization form KC + for (int cp : Tables.mapWithNfkc(codePoint)) { + mapping.appendCodePoint(cp); + } + } else if (!normalizeKc && caseFoldNoNormalization) { + // while appendix B.3 is for profiles that do + // not use Unicode normalization + for (int cp : Tables.mapWithoutNormalization(codePoint)) { + mapping.appendCodePoint(cp); + } + } else if (additionalMapping) { + // - Any additional mapping tables specific to the profile + for (int cp : profile.additionalMappingTable(codePoint)) { + mapping.appendCodePoint(cp); + } + } else { + mapping.appendCodePoint(codePoint); + } + } + + char[] arr = new char[mapping.length()]; + mapping.getChars(0, mapping.length(), arr, 0); + return arr; + } + + private void prohibitedOutput(int codePoint) { + // - Any additional characters that are prohibited as output specific to + // the profile + checkProhibited(forbidAdditionalCharacters, profile::prohibitedAdditionalCharacters, + codePoint, "Prohibited code point"); + + checkProhibited(forbidAsciiSpaces, Tables::prohibitionAsciiSpace, + codePoint, "Prohibited ASCII space"); + checkProhibited(forbidNonAsciiSpaces, Tables::prohibitionNonAsciiSpace, + codePoint, "Prohibited non-ASCII space"); + checkProhibited(forbidAsciiControl, Tables::prohibitionAsciiControl, + codePoint, "Prohibited ASCII control"); + checkProhibited(forbidNonAsciiControl, Tables::prohibitionNonAsciiControl, + codePoint, "Prohibited non-ASCII control"); + checkProhibited(forbidPrivateUse, Tables::prohibitionPrivateUse, + codePoint, "Prohibited private use character"); + checkProhibited(forbidNonCharacter, Tables::prohibitionNonCharacterCodePoints, + codePoint, "Prohibited non-character code point"); + checkProhibited(forbidSurrogate, Tables::prohibitionSurrogateCodes, + codePoint, "Prohibited surrogate code point"); + checkProhibited(forbidInappropriatePlainText, Tables::prohibitionInappropriatePlainText, + codePoint, "Prohibited plain text code point"); + checkProhibited(forbidInappropriateCanonRep, + Tables::prohibitionInappropriateCanonicalRepresentation, + codePoint, "Prohibited non-canonical code point"); + checkProhibited(forbidChangeDisplayDeprecated, Tables::prohibitionChangeDisplayProperties, + codePoint, "Prohibited control character"); + checkProhibited(forbidTagging, Tables::prohibitionTaggingCharacters, + codePoint, "Prohibited tagging character"); + + // All code points not assigned in the character repertoire named in a + // stringprep profile are called "unassigned code points". Stored + // strings using the profile MUST NOT contain any unassigned code + // points. Queries for matching strings MAY contain unassigned code + // points. + checkProhibited(forbidUnassigned, Tables::unassignedCodePoints, + codePoint, "Unassigned code point"); + } + + private static void checkProhibited(boolean forbid, IntPredicate tableCheck, int codePoint, + String msg) { + if (forbid && tableCheck.test(codePoint)) { + throw new IllegalArgumentException( + String.format(Locale.ROOT, "%s \"0x%04X\"", msg, codePoint)); + } + } + +} diff --git a/stringprep/src/main/java/com/ongres/stringprep/StringprepLocator.java b/stringprep/src/main/java/com/ongres/stringprep/StringprepLocator.java new file mode 100644 index 0000000..feb2f72 --- /dev/null +++ b/stringprep/src/main/java/com/ongres/stringprep/StringprepLocator.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep; + +import java.util.ServiceLoader; + +final class StringprepLocator { + + private StringprepLocator() { + // Internal utility class + } + + static Profile getProfile(String profileName) { + for (Profile profile : ServiceLoader.load(Profile.class)) { + ProfileName annotation = profile.getClass().getDeclaredAnnotation(ProfileName.class); + if (annotation != null && annotation.value().equals(profileName)) { + return profile; + } + } + return null; + } + +} diff --git a/stringprep/src/main/java/com/ongres/stringprep/Tables.java b/stringprep/src/main/java/com/ongres/stringprep/Tables.java new file mode 100644 index 0000000..2f071f4 --- /dev/null +++ b/stringprep/src/main/java/com/ongres/stringprep/Tables.java @@ -0,0 +1,5549 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package com.ongres.stringprep; + +// AUTO-GENERATED FILE - DO NOT EDIT! + +/** + * Expose tables parsed from the StringPrep RFC-3454. + */ +public final class Tables { + + private Tables() { + throw new AssertionError(); + } + + /** + * Unassigned code points in Unicode 3.2. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Unassigned code points in Unicode 3.2". + * @see RFC 3454, Appendix A.1 + */ + public static boolean unassignedCodePoints(int codePoint) { + return codePoint == 0x0221 + || (codePoint >= 0x0234 && codePoint <= 0x024F) + || (codePoint >= 0x02AE && codePoint <= 0x02AF) + || (codePoint >= 0x02EF && codePoint <= 0x02FF) + || (codePoint >= 0x0350 && codePoint <= 0x035F) + || (codePoint >= 0x0370 && codePoint <= 0x0373) + || (codePoint >= 0x0376 && codePoint <= 0x0379) + || (codePoint >= 0x037B && codePoint <= 0x037D) + || (codePoint >= 0x037F && codePoint <= 0x0383) + || codePoint == 0x038B + || codePoint == 0x038D + || codePoint == 0x03A2 + || codePoint == 0x03CF + || (codePoint >= 0x03F7 && codePoint <= 0x03FF) + || codePoint == 0x0487 + || codePoint == 0x04CF + || (codePoint >= 0x04F6 && codePoint <= 0x04F7) + || (codePoint >= 0x04FA && codePoint <= 0x04FF) + || (codePoint >= 0x0510 && codePoint <= 0x0530) + || (codePoint >= 0x0557 && codePoint <= 0x0558) + || codePoint == 0x0560 + || codePoint == 0x0588 + || (codePoint >= 0x058B && codePoint <= 0x0590) + || codePoint == 0x05A2 + || codePoint == 0x05BA + || (codePoint >= 0x05C5 && codePoint <= 0x05CF) + || (codePoint >= 0x05EB && codePoint <= 0x05EF) + || (codePoint >= 0x05F5 && codePoint <= 0x060B) + || (codePoint >= 0x060D && codePoint <= 0x061A) + || (codePoint >= 0x061C && codePoint <= 0x061E) + || codePoint == 0x0620 + || (codePoint >= 0x063B && codePoint <= 0x063F) + || (codePoint >= 0x0656 && codePoint <= 0x065F) + || (codePoint >= 0x06EE && codePoint <= 0x06EF) + || codePoint == 0x06FF + || codePoint == 0x070E + || (codePoint >= 0x072D && codePoint <= 0x072F) + || (codePoint >= 0x074B && codePoint <= 0x077F) + || (codePoint >= 0x07B2 && codePoint <= 0x0900) + || codePoint == 0x0904 + || (codePoint >= 0x093A && codePoint <= 0x093B) + || (codePoint >= 0x094E && codePoint <= 0x094F) + || (codePoint >= 0x0955 && codePoint <= 0x0957) + || (codePoint >= 0x0971 && codePoint <= 0x0980) + || codePoint == 0x0984 + || (codePoint >= 0x098D && codePoint <= 0x098E) + || (codePoint >= 0x0991 && codePoint <= 0x0992) + || codePoint == 0x09A9 + || codePoint == 0x09B1 + || (codePoint >= 0x09B3 && codePoint <= 0x09B5) + || (codePoint >= 0x09BA && codePoint <= 0x09BB) + || codePoint == 0x09BD + || (codePoint >= 0x09C5 && codePoint <= 0x09C6) + || (codePoint >= 0x09C9 && codePoint <= 0x09CA) + || (codePoint >= 0x09CE && codePoint <= 0x09D6) + || (codePoint >= 0x09D8 && codePoint <= 0x09DB) + || codePoint == 0x09DE + || (codePoint >= 0x09E4 && codePoint <= 0x09E5) + || (codePoint >= 0x09FB && codePoint <= 0x0A01) + || (codePoint >= 0x0A03 && codePoint <= 0x0A04) + || (codePoint >= 0x0A0B && codePoint <= 0x0A0E) + || (codePoint >= 0x0A11 && codePoint <= 0x0A12) + || codePoint == 0x0A29 + || codePoint == 0x0A31 + || codePoint == 0x0A34 + || codePoint == 0x0A37 + || (codePoint >= 0x0A3A && codePoint <= 0x0A3B) + || codePoint == 0x0A3D + || (codePoint >= 0x0A43 && codePoint <= 0x0A46) + || (codePoint >= 0x0A49 && codePoint <= 0x0A4A) + || (codePoint >= 0x0A4E && codePoint <= 0x0A58) + || codePoint == 0x0A5D + || (codePoint >= 0x0A5F && codePoint <= 0x0A65) + || (codePoint >= 0x0A75 && codePoint <= 0x0A80) + || codePoint == 0x0A84 + || codePoint == 0x0A8C + || codePoint == 0x0A8E + || codePoint == 0x0A92 + || codePoint == 0x0AA9 + || codePoint == 0x0AB1 + || codePoint == 0x0AB4 + || (codePoint >= 0x0ABA && codePoint <= 0x0ABB) + || codePoint == 0x0AC6 + || codePoint == 0x0ACA + || (codePoint >= 0x0ACE && codePoint <= 0x0ACF) + || (codePoint >= 0x0AD1 && codePoint <= 0x0ADF) + || (codePoint >= 0x0AE1 && codePoint <= 0x0AE5) + || (codePoint >= 0x0AF0 && codePoint <= 0x0B00) + || codePoint == 0x0B04 + || (codePoint >= 0x0B0D && codePoint <= 0x0B0E) + || (codePoint >= 0x0B11 && codePoint <= 0x0B12) + || codePoint == 0x0B29 + || codePoint == 0x0B31 + || (codePoint >= 0x0B34 && codePoint <= 0x0B35) + || (codePoint >= 0x0B3A && codePoint <= 0x0B3B) + || (codePoint >= 0x0B44 && codePoint <= 0x0B46) + || (codePoint >= 0x0B49 && codePoint <= 0x0B4A) + || (codePoint >= 0x0B4E && codePoint <= 0x0B55) + || (codePoint >= 0x0B58 && codePoint <= 0x0B5B) + || codePoint == 0x0B5E + || (codePoint >= 0x0B62 && codePoint <= 0x0B65) + || (codePoint >= 0x0B71 && codePoint <= 0x0B81) + || codePoint == 0x0B84 + || (codePoint >= 0x0B8B && codePoint <= 0x0B8D) + || codePoint == 0x0B91 + || (codePoint >= 0x0B96 && codePoint <= 0x0B98) + || codePoint == 0x0B9B + || codePoint == 0x0B9D + || (codePoint >= 0x0BA0 && codePoint <= 0x0BA2) + || (codePoint >= 0x0BA5 && codePoint <= 0x0BA7) + || (codePoint >= 0x0BAB && codePoint <= 0x0BAD) + || codePoint == 0x0BB6 + || (codePoint >= 0x0BBA && codePoint <= 0x0BBD) + || (codePoint >= 0x0BC3 && codePoint <= 0x0BC5) + || codePoint == 0x0BC9 + || (codePoint >= 0x0BCE && codePoint <= 0x0BD6) + || (codePoint >= 0x0BD8 && codePoint <= 0x0BE6) + || (codePoint >= 0x0BF3 && codePoint <= 0x0C00) + || codePoint == 0x0C04 + || codePoint == 0x0C0D + || codePoint == 0x0C11 + || codePoint == 0x0C29 + || codePoint == 0x0C34 + || (codePoint >= 0x0C3A && codePoint <= 0x0C3D) + || codePoint == 0x0C45 + || codePoint == 0x0C49 + || (codePoint >= 0x0C4E && codePoint <= 0x0C54) + || (codePoint >= 0x0C57 && codePoint <= 0x0C5F) + || (codePoint >= 0x0C62 && codePoint <= 0x0C65) + || (codePoint >= 0x0C70 && codePoint <= 0x0C81) + || codePoint == 0x0C84 + || codePoint == 0x0C8D + || codePoint == 0x0C91 + || codePoint == 0x0CA9 + || codePoint == 0x0CB4 + || (codePoint >= 0x0CBA && codePoint <= 0x0CBD) + || codePoint == 0x0CC5 + || codePoint == 0x0CC9 + || (codePoint >= 0x0CCE && codePoint <= 0x0CD4) + || (codePoint >= 0x0CD7 && codePoint <= 0x0CDD) + || codePoint == 0x0CDF + || (codePoint >= 0x0CE2 && codePoint <= 0x0CE5) + || (codePoint >= 0x0CF0 && codePoint <= 0x0D01) + || codePoint == 0x0D04 + || codePoint == 0x0D0D + || codePoint == 0x0D11 + || codePoint == 0x0D29 + || (codePoint >= 0x0D3A && codePoint <= 0x0D3D) + || (codePoint >= 0x0D44 && codePoint <= 0x0D45) + || codePoint == 0x0D49 + || (codePoint >= 0x0D4E && codePoint <= 0x0D56) + || (codePoint >= 0x0D58 && codePoint <= 0x0D5F) + || (codePoint >= 0x0D62 && codePoint <= 0x0D65) + || (codePoint >= 0x0D70 && codePoint <= 0x0D81) + || codePoint == 0x0D84 + || (codePoint >= 0x0D97 && codePoint <= 0x0D99) + || codePoint == 0x0DB2 + || codePoint == 0x0DBC + || (codePoint >= 0x0DBE && codePoint <= 0x0DBF) + || (codePoint >= 0x0DC7 && codePoint <= 0x0DC9) + || (codePoint >= 0x0DCB && codePoint <= 0x0DCE) + || codePoint == 0x0DD5 + || codePoint == 0x0DD7 + || (codePoint >= 0x0DE0 && codePoint <= 0x0DF1) + || (codePoint >= 0x0DF5 && codePoint <= 0x0E00) + || (codePoint >= 0x0E3B && codePoint <= 0x0E3E) + || (codePoint >= 0x0E5C && codePoint <= 0x0E80) + || codePoint == 0x0E83 + || (codePoint >= 0x0E85 && codePoint <= 0x0E86) + || codePoint == 0x0E89 + || (codePoint >= 0x0E8B && codePoint <= 0x0E8C) + || (codePoint >= 0x0E8E && codePoint <= 0x0E93) + || codePoint == 0x0E98 + || codePoint == 0x0EA0 + || codePoint == 0x0EA4 + || codePoint == 0x0EA6 + || (codePoint >= 0x0EA8 && codePoint <= 0x0EA9) + || codePoint == 0x0EAC + || codePoint == 0x0EBA + || (codePoint >= 0x0EBE && codePoint <= 0x0EBF) + || codePoint == 0x0EC5 + || codePoint == 0x0EC7 + || (codePoint >= 0x0ECE && codePoint <= 0x0ECF) + || (codePoint >= 0x0EDA && codePoint <= 0x0EDB) + || (codePoint >= 0x0EDE && codePoint <= 0x0EFF) + || codePoint == 0x0F48 + || (codePoint >= 0x0F6B && codePoint <= 0x0F70) + || (codePoint >= 0x0F8C && codePoint <= 0x0F8F) + || codePoint == 0x0F98 + || codePoint == 0x0FBD + || (codePoint >= 0x0FCD && codePoint <= 0x0FCE) + || (codePoint >= 0x0FD0 && codePoint <= 0x0FFF) + || codePoint == 0x1022 + || codePoint == 0x1028 + || codePoint == 0x102B + || (codePoint >= 0x1033 && codePoint <= 0x1035) + || (codePoint >= 0x103A && codePoint <= 0x103F) + || (codePoint >= 0x105A && codePoint <= 0x109F) + || (codePoint >= 0x10C6 && codePoint <= 0x10CF) + || (codePoint >= 0x10F9 && codePoint <= 0x10FA) + || (codePoint >= 0x10FC && codePoint <= 0x10FF) + || (codePoint >= 0x115A && codePoint <= 0x115E) + || (codePoint >= 0x11A3 && codePoint <= 0x11A7) + || (codePoint >= 0x11FA && codePoint <= 0x11FF) + || codePoint == 0x1207 + || codePoint == 0x1247 + || codePoint == 0x1249 + || (codePoint >= 0x124E && codePoint <= 0x124F) + || codePoint == 0x1257 + || codePoint == 0x1259 + || (codePoint >= 0x125E && codePoint <= 0x125F) + || codePoint == 0x1287 + || codePoint == 0x1289 + || (codePoint >= 0x128E && codePoint <= 0x128F) + || codePoint == 0x12AF + || codePoint == 0x12B1 + || (codePoint >= 0x12B6 && codePoint <= 0x12B7) + || codePoint == 0x12BF + || codePoint == 0x12C1 + || (codePoint >= 0x12C6 && codePoint <= 0x12C7) + || codePoint == 0x12CF + || codePoint == 0x12D7 + || codePoint == 0x12EF + || codePoint == 0x130F + || codePoint == 0x1311 + || (codePoint >= 0x1316 && codePoint <= 0x1317) + || codePoint == 0x131F + || codePoint == 0x1347 + || (codePoint >= 0x135B && codePoint <= 0x1360) + || (codePoint >= 0x137D && codePoint <= 0x139F) + || (codePoint >= 0x13F5 && codePoint <= 0x1400) + || (codePoint >= 0x1677 && codePoint <= 0x167F) + || (codePoint >= 0x169D && codePoint <= 0x169F) + || (codePoint >= 0x16F1 && codePoint <= 0x16FF) + || codePoint == 0x170D + || (codePoint >= 0x1715 && codePoint <= 0x171F) + || (codePoint >= 0x1737 && codePoint <= 0x173F) + || (codePoint >= 0x1754 && codePoint <= 0x175F) + || codePoint == 0x176D + || codePoint == 0x1771 + || (codePoint >= 0x1774 && codePoint <= 0x177F) + || (codePoint >= 0x17DD && codePoint <= 0x17DF) + || (codePoint >= 0x17EA && codePoint <= 0x17FF) + || codePoint == 0x180F + || (codePoint >= 0x181A && codePoint <= 0x181F) + || (codePoint >= 0x1878 && codePoint <= 0x187F) + || (codePoint >= 0x18AA && codePoint <= 0x1DFF) + || (codePoint >= 0x1E9C && codePoint <= 0x1E9F) + || (codePoint >= 0x1EFA && codePoint <= 0x1EFF) + || (codePoint >= 0x1F16 && codePoint <= 0x1F17) + || (codePoint >= 0x1F1E && codePoint <= 0x1F1F) + || (codePoint >= 0x1F46 && codePoint <= 0x1F47) + || (codePoint >= 0x1F4E && codePoint <= 0x1F4F) + || codePoint == 0x1F58 + || codePoint == 0x1F5A + || codePoint == 0x1F5C + || codePoint == 0x1F5E + || (codePoint >= 0x1F7E && codePoint <= 0x1F7F) + || codePoint == 0x1FB5 + || codePoint == 0x1FC5 + || (codePoint >= 0x1FD4 && codePoint <= 0x1FD5) + || codePoint == 0x1FDC + || (codePoint >= 0x1FF0 && codePoint <= 0x1FF1) + || codePoint == 0x1FF5 + || codePoint == 0x1FFF + || (codePoint >= 0x2053 && codePoint <= 0x2056) + || (codePoint >= 0x2058 && codePoint <= 0x205E) + || (codePoint >= 0x2064 && codePoint <= 0x2069) + || (codePoint >= 0x2072 && codePoint <= 0x2073) + || (codePoint >= 0x208F && codePoint <= 0x209F) + || (codePoint >= 0x20B2 && codePoint <= 0x20CF) + || (codePoint >= 0x20EB && codePoint <= 0x20FF) + || (codePoint >= 0x213B && codePoint <= 0x213C) + || (codePoint >= 0x214C && codePoint <= 0x2152) + || (codePoint >= 0x2184 && codePoint <= 0x218F) + || (codePoint >= 0x23CF && codePoint <= 0x23FF) + || (codePoint >= 0x2427 && codePoint <= 0x243F) + || (codePoint >= 0x244B && codePoint <= 0x245F) + || codePoint == 0x24FF + || (codePoint >= 0x2614 && codePoint <= 0x2615) + || codePoint == 0x2618 + || (codePoint >= 0x267E && codePoint <= 0x267F) + || (codePoint >= 0x268A && codePoint <= 0x2700) + || codePoint == 0x2705 + || (codePoint >= 0x270A && codePoint <= 0x270B) + || codePoint == 0x2728 + || codePoint == 0x274C + || codePoint == 0x274E + || (codePoint >= 0x2753 && codePoint <= 0x2755) + || codePoint == 0x2757 + || (codePoint >= 0x275F && codePoint <= 0x2760) + || (codePoint >= 0x2795 && codePoint <= 0x2797) + || codePoint == 0x27B0 + || (codePoint >= 0x27BF && codePoint <= 0x27CF) + || (codePoint >= 0x27EC && codePoint <= 0x27EF) + || (codePoint >= 0x2B00 && codePoint <= 0x2E7F) + || codePoint == 0x2E9A + || (codePoint >= 0x2EF4 && codePoint <= 0x2EFF) + || (codePoint >= 0x2FD6 && codePoint <= 0x2FEF) + || (codePoint >= 0x2FFC && codePoint <= 0x2FFF) + || codePoint == 0x3040 + || (codePoint >= 0x3097 && codePoint <= 0x3098) + || (codePoint >= 0x3100 && codePoint <= 0x3104) + || (codePoint >= 0x312D && codePoint <= 0x3130) + || codePoint == 0x318F + || (codePoint >= 0x31B8 && codePoint <= 0x31EF) + || (codePoint >= 0x321D && codePoint <= 0x321F) + || (codePoint >= 0x3244 && codePoint <= 0x3250) + || (codePoint >= 0x327C && codePoint <= 0x327E) + || (codePoint >= 0x32CC && codePoint <= 0x32CF) + || codePoint == 0x32FF + || (codePoint >= 0x3377 && codePoint <= 0x337A) + || (codePoint >= 0x33DE && codePoint <= 0x33DF) + || codePoint == 0x33FF + || (codePoint >= 0x4DB6 && codePoint <= 0x4DFF) + || (codePoint >= 0x9FA6 && codePoint <= 0x9FFF) + || (codePoint >= 0xA48D && codePoint <= 0xA48F) + || (codePoint >= 0xA4C7 && codePoint <= 0xABFF) + || (codePoint >= 0xD7A4 && codePoint <= 0xD7FF) + || (codePoint >= 0xFA2E && codePoint <= 0xFA2F) + || (codePoint >= 0xFA6B && codePoint <= 0xFAFF) + || (codePoint >= 0xFB07 && codePoint <= 0xFB12) + || (codePoint >= 0xFB18 && codePoint <= 0xFB1C) + || codePoint == 0xFB37 + || codePoint == 0xFB3D + || codePoint == 0xFB3F + || codePoint == 0xFB42 + || codePoint == 0xFB45 + || (codePoint >= 0xFBB2 && codePoint <= 0xFBD2) + || (codePoint >= 0xFD40 && codePoint <= 0xFD4F) + || (codePoint >= 0xFD90 && codePoint <= 0xFD91) + || (codePoint >= 0xFDC8 && codePoint <= 0xFDCF) + || (codePoint >= 0xFDFD && codePoint <= 0xFDFF) + || (codePoint >= 0xFE10 && codePoint <= 0xFE1F) + || (codePoint >= 0xFE24 && codePoint <= 0xFE2F) + || (codePoint >= 0xFE47 && codePoint <= 0xFE48) + || codePoint == 0xFE53 + || codePoint == 0xFE67 + || (codePoint >= 0xFE6C && codePoint <= 0xFE6F) + || codePoint == 0xFE75 + || (codePoint >= 0xFEFD && codePoint <= 0xFEFE) + || codePoint == 0xFF00 + || (codePoint >= 0xFFBF && codePoint <= 0xFFC1) + || (codePoint >= 0xFFC8 && codePoint <= 0xFFC9) + || (codePoint >= 0xFFD0 && codePoint <= 0xFFD1) + || (codePoint >= 0xFFD8 && codePoint <= 0xFFD9) + || (codePoint >= 0xFFDD && codePoint <= 0xFFDF) + || codePoint == 0xFFE7 + || (codePoint >= 0xFFEF && codePoint <= 0xFFF8) + || (codePoint >= 0x10000 && codePoint <= 0x102FF) + || codePoint == 0x1031F + || (codePoint >= 0x10324 && codePoint <= 0x1032F) + || (codePoint >= 0x1034B && codePoint <= 0x103FF) + || (codePoint >= 0x10426 && codePoint <= 0x10427) + || (codePoint >= 0x1044E && codePoint <= 0x1CFFF) + || (codePoint >= 0x1D0F6 && codePoint <= 0x1D0FF) + || (codePoint >= 0x1D127 && codePoint <= 0x1D129) + || (codePoint >= 0x1D1DE && codePoint <= 0x1D3FF) + || codePoint == 0x1D455 + || codePoint == 0x1D49D + || (codePoint >= 0x1D4A0 && codePoint <= 0x1D4A1) + || (codePoint >= 0x1D4A3 && codePoint <= 0x1D4A4) + || (codePoint >= 0x1D4A7 && codePoint <= 0x1D4A8) + || codePoint == 0x1D4AD + || codePoint == 0x1D4BA + || codePoint == 0x1D4BC + || codePoint == 0x1D4C1 + || codePoint == 0x1D4C4 + || codePoint == 0x1D506 + || (codePoint >= 0x1D50B && codePoint <= 0x1D50C) + || codePoint == 0x1D515 + || codePoint == 0x1D51D + || codePoint == 0x1D53A + || codePoint == 0x1D53F + || codePoint == 0x1D545 + || (codePoint >= 0x1D547 && codePoint <= 0x1D549) + || codePoint == 0x1D551 + || (codePoint >= 0x1D6A4 && codePoint <= 0x1D6A7) + || (codePoint >= 0x1D7CA && codePoint <= 0x1D7CD) + || (codePoint >= 0x1D800 && codePoint <= 0x1FFFD) + || (codePoint >= 0x2A6D7 && codePoint <= 0x2F7FF) + || (codePoint >= 0x2FA1E && codePoint <= 0x2FFFD) + || (codePoint >= 0x30000 && codePoint <= 0x3FFFD) + || (codePoint >= 0x40000 && codePoint <= 0x4FFFD) + || (codePoint >= 0x50000 && codePoint <= 0x5FFFD) + || (codePoint >= 0x60000 && codePoint <= 0x6FFFD) + || (codePoint >= 0x70000 && codePoint <= 0x7FFFD) + || (codePoint >= 0x80000 && codePoint <= 0x8FFFD) + || (codePoint >= 0x90000 && codePoint <= 0x9FFFD) + || (codePoint >= 0xA0000 && codePoint <= 0xAFFFD) + || (codePoint >= 0xB0000 && codePoint <= 0xBFFFD) + || (codePoint >= 0xC0000 && codePoint <= 0xCFFFD) + || (codePoint >= 0xD0000 && codePoint <= 0xDFFFD) + || codePoint == 0xE0000 + || (codePoint >= 0xE0002 && codePoint <= 0xE001F) + || (codePoint >= 0xE0080 && codePoint <= 0xEFFFD) + + ; + } + + /** + * Commonly mapped to nothing. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Commonly mapped to nothing". + * @see RFC 3454, Appendix B.1 + */ + public static boolean mapToNothing(int codePoint) { + return codePoint == 0x00AD + || codePoint == 0x034F + || codePoint == 0x1806 + || codePoint == 0x180B + || codePoint == 0x180C + || codePoint == 0x180D + || codePoint == 0x200B + || codePoint == 0x200C + || codePoint == 0x200D + || codePoint == 0x2060 + || codePoint == 0xFE00 + || codePoint == 0xFE01 + || codePoint == 0xFE02 + || codePoint == 0xFE03 + || codePoint == 0xFE04 + || codePoint == 0xFE05 + || codePoint == 0xFE06 + || codePoint == 0xFE07 + || codePoint == 0xFE08 + || codePoint == 0xFE09 + || codePoint == 0xFE0A + || codePoint == 0xFE0B + || codePoint == 0xFE0C + || codePoint == 0xFE0D + || codePoint == 0xFE0E + || codePoint == 0xFE0F + || codePoint == 0xFEFF + + ; + } + + /** + * Mapping for case-folding used with NFKC. + * + * @param codePoint the character (Unicode code point) to be mapped. + * @return Case-folding used with NFKC for the given {@code codePoint}. + * @see RFC 3454, Appendix B.2 + */ + public static int[] mapWithNfkc(int codePoint) { + switch (codePoint) { + case 0x00C5: + return new int[] {0x00E5}; + case 0x00C6: + return new int[] {0x00E6}; + case 0x00C3: + return new int[] {0x00E3}; + case 0x00C4: + return new int[] {0x00E4}; + case 0x00C9: + return new int[] {0x00E9}; + case 0x00C7: + return new int[] {0x00E7}; + case 0x00C8: + return new int[] {0x00E8}; + case 0x1D6D3: + return new int[] {0x03C3}; + case 0x00C1: + return new int[] {0x00E1}; + case 0x00C2: + return new int[] {0x00E2}; + case 0x00C0: + return new int[] {0x00E0}; + case 0x00D6: + return new int[] {0x00F6}; + case 0x00D4: + return new int[] {0x00F4}; + case 0x00D5: + return new int[] {0x00F5}; + case 0x00D8: + return new int[] {0x00F8}; + case 0x00D9: + return new int[] {0x00F9}; + case 0x1D4A2: + return new int[] {0x0067}; + case 0x1D6E4: + return new int[] {0x03B3}; + case 0x1D6E5: + return new int[] {0x03B4}; + case 0x1D6E2: + return new int[] {0x03B1}; + case 0x1D6E3: + return new int[] {0x03B2}; + case 0x00D2: + return new int[] {0x00F2}; + case 0x1D4A6: + return new int[] {0x006B}; + case 0x1D6E8: + return new int[] {0x03B7}; + case 0x00D3: + return new int[] {0x00F3}; + case 0x1D6E9: + return new int[] {0x03B8}; + case 0x00D0: + return new int[] {0x00F0}; + case 0x1D6E6: + return new int[] {0x03B5}; + case 0x00D1: + return new int[] {0x00F1}; + case 0x1D4A5: + return new int[] {0x006A}; + case 0x1D6E7: + return new int[] {0x03B6}; + case 0x00CE: + return new int[] {0x00EE}; + case 0x00CF: + return new int[] {0x00EF}; + case 0x00CC: + return new int[] {0x00EC}; + case 0x00CD: + return new int[] {0x00ED}; + case 0x1D4A9: + return new int[] {0x006E}; + case 0x1D6EA: + return new int[] {0x03B9}; + case 0x1D4AB: + return new int[] {0x0070}; + case 0x1D6ED: + return new int[] {0x03BC}; + case 0x1D4AC: + return new int[] {0x0071}; + case 0x1D6EE: + return new int[] {0x03BD}; + case 0x1D6EB: + return new int[] {0x03BA}; + case 0x1D4AA: + return new int[] {0x006F}; + case 0x1D6EC: + return new int[] {0x03BB}; + case 0x00CA: + return new int[] {0x00EA}; + case 0x1D4AF: + return new int[] {0x0074}; + case 0x00CB: + return new int[] {0x00EB}; + case 0x1D6EF: + return new int[] {0x03BE}; + case 0x1D4AE: + return new int[] {0x0073}; + case 0x33B5: + return new int[] {0x006E, 0x0076}; + case 0x33B4: + return new int[] {0x0070, 0x0076}; + case 0x1D6AF: + return new int[] {0x03B8}; + case 0x33B9: + return new int[] {0x006D, 0x0076}; + case 0x33B8: + return new int[] {0x006B, 0x0076}; + case 0x33B7: + return new int[] {0x006D, 0x0076}; + case 0x33B6: + return new int[] {0x03BC, 0x0076}; + case 0x1D6B1: + return new int[] {0x03BA}; + case 0x1D6B2: + return new int[] {0x03BB}; + case 0x1D6B0: + return new int[] {0x03B9}; + case 0x1D6B5: + return new int[] {0x03BE}; + case 0x1D6B6: + return new int[] {0x03BF}; + case 0x1D6B3: + return new int[] {0x03BC}; + case 0x1D6B4: + return new int[] {0x03BD}; + case 0x00DF: + return new int[] {0x0073, 0x0073}; + case 0x1D6B9: + return new int[] {0x03B8}; + case 0x33AC: + return new int[] {0x0067, 0x0070, 0x0061}; + case 0x00DD: + return new int[] {0x00FD}; + case 0x33AB: + return new int[] {0x006D, 0x0070, 0x0061}; + case 0x1D6B7: + return new int[] {0x03C0}; + case 0x00DE: + return new int[] {0x00FE}; + case 0x33AA: + return new int[] {0x006B, 0x0070, 0x0061}; + case 0x1D6B8: + return new int[] {0x03C1}; + case 0x1D6BA: + return new int[] {0x03C3}; + case 0x1D6BB: + return new int[] {0x03C4}; + case 0x33A9: + return new int[] {0x0070, 0x0061}; + case 0x00DB: + return new int[] {0x00FB}; + case 0x1D6BE: + return new int[] {0x03C7}; + case 0x00DC: + return new int[] {0x00FC}; + case 0x1D6BF: + return new int[] {0x03C8}; + case 0x1D6BC: + return new int[] {0x03C5}; + case 0x00DA: + return new int[] {0x00FA}; + case 0x1D6BD: + return new int[] {0x03C6}; + case 0x33C6: + return new int[] {0x0063, 0x2215, 0x006B, 0x0067}; + case 0x33C3: + return new int[] {0x0062, 0x0071}; + case 0x33C9: + return new int[] {0x0067, 0x0079}; + case 0x33C8: + return new int[] {0x0064, 0x0062}; + case 0x33C7: + return new int[] {0x0063, 0x006F, 0x002E}; + case 0x1D6C0: + return new int[] {0x03C9}; + case 0x33C1: + return new int[] {0x006D, 0x03C9}; + case 0x33C0: + return new int[] {0x006B, 0x03C9}; + case 0x33BE: + return new int[] {0x006B, 0x0077}; + case 0x33BD: + return new int[] {0x006D, 0x0077}; + case 0x33BC: + return new int[] {0x03BC, 0x0077}; + case 0x33BB: + return new int[] {0x006E, 0x0077}; + case 0x33BF: + return new int[] {0x006D, 0x0077}; + case 0x33BA: + return new int[] {0x0070, 0x0077}; + case 0x24B7: + return new int[] {0x24D1}; + case 0x24B6: + return new int[] {0x24D0}; + case 0x1D6A8: + return new int[] {0x03B1}; + case 0x1D6A9: + return new int[] {0x03B2}; + case 0x1D6AA: + return new int[] {0x03B3}; + case 0x1D6AD: + return new int[] {0x03B6}; + case 0x1D6AE: + return new int[] {0x03B7}; + case 0x1D6AB: + return new int[] {0x03B4}; + case 0x1D6AC: + return new int[] {0x03B5}; + case 0x24C4: + return new int[] {0x24DE}; + case 0x24C3: + return new int[] {0x24DD}; + case 0x1D49C: + return new int[] {0x0061}; + case 0x24C2: + return new int[] {0x24DC}; + case 0x24C1: + return new int[] {0x24DB}; + case 0x24C8: + return new int[] {0x24E2}; + case 0x1D49F: + return new int[] {0x0064}; + case 0x24C7: + return new int[] {0x24E1}; + case 0x24C6: + return new int[] {0x24E0}; + case 0x24C5: + return new int[] {0x24DF}; + case 0x1D49E: + return new int[] {0x0063}; + case 0x24C0: + return new int[] {0x24DA}; + case 0x24BC: + return new int[] {0x24D6}; + case 0x24BB: + return new int[] {0x24D5}; + case 0x24BA: + return new int[] {0x24D4}; + case 0x24BF: + return new int[] {0x24D9}; + case 0x24BE: + return new int[] {0x24D8}; + case 0x24BD: + return new int[] {0x24D7}; + case 0x24B9: + return new int[] {0x24D3}; + case 0x24B8: + return new int[] {0x24D2}; + case 0x00B5: + return new int[] {0x03BC}; + case 0x24CD: + return new int[] {0x24E7}; + case 0x24CC: + return new int[] {0x24E6}; + case 0x24CB: + return new int[] {0x24E5}; + case 0x24CA: + return new int[] {0x24E4}; + case 0x24CF: + return new int[] {0x24E9}; + case 0x24CE: + return new int[] {0x24E8}; + case 0x24C9: + return new int[] {0x24E3}; + case 0x054A: + return new int[] {0x057A}; + case 0x054B: + return new int[] {0x057B}; + case 0x1E10: + return new int[] {0x1E11}; + case 0x054E: + return new int[] {0x057E}; + case 0x054F: + return new int[] {0x057F}; + case 0x1E14: + return new int[] {0x1E15}; + case 0x054C: + return new int[] {0x057C}; + case 0x054D: + return new int[] {0x057D}; + case 0x1E12: + return new int[] {0x1E13}; + case 0x0549: + return new int[] {0x0579}; + case 0x0547: + return new int[] {0x0577}; + case 0x0548: + return new int[] {0x0578}; + case 0x1E0E: + return new int[] {0x1E0F}; + case 0x0541: + return new int[] {0x0571}; + case 0x0542: + return new int[] {0x0572}; + case 0x0540: + return new int[] {0x0570}; + case 0x0545: + return new int[] {0x0575}; + case 0x0546: + return new int[] {0x0576}; + case 0x1E0C: + return new int[] {0x1E0D}; + case 0x0543: + return new int[] {0x0573}; + case 0x0544: + return new int[] {0x0574}; + case 0x1E0A: + return new int[] {0x1E0B}; + case 0x1E06: + return new int[] {0x1E07}; + case 0x053F: + return new int[] {0x056F}; + case 0x1E04: + return new int[] {0x1E05}; + case 0x1E08: + return new int[] {0x1E09}; + case 0x1E20: + return new int[] {0x1E21}; + case 0x1E24: + return new int[] {0x1E25}; + case 0x1E22: + return new int[] {0x1E23}; + case 0x1E1E: + return new int[] {0x1E1F}; + case 0x0552: + return new int[] {0x0582}; + case 0x0553: + return new int[] {0x0583}; + case 0x0550: + return new int[] {0x0580}; + case 0x0551: + return new int[] {0x0581}; + case 0x0556: + return new int[] {0x0586}; + case 0x1E1C: + return new int[] {0x1E1D}; + case 0x0554: + return new int[] {0x0584}; + case 0x1E1A: + return new int[] {0x1E1B}; + case 0x0555: + return new int[] {0x0585}; + case 0x1E18: + return new int[] {0x1E19}; + case 0x1E16: + return new int[] {0x1E17}; + case 0x1E32: + return new int[] {0x1E33}; + case 0x1E30: + return new int[] {0x1E31}; + case 0x1E36: + return new int[] {0x1E37}; + case 0x1E34: + return new int[] {0x1E35}; + case 0x1E2A: + return new int[] {0x1E2B}; + case 0x1E2E: + return new int[] {0x1E2F}; + case 0x1E2C: + return new int[] {0x1E2D}; + case 0x1E28: + return new int[] {0x1E29}; + case 0x1E26: + return new int[] {0x1E27}; + case 0x1E42: + return new int[] {0x1E43}; + case 0x1E40: + return new int[] {0x1E41}; + case 0x1E46: + return new int[] {0x1E47}; + case 0x1E44: + return new int[] {0x1E45}; + case 0x1E3A: + return new int[] {0x1E3B}; + case 0x1E3E: + return new int[] {0x1E3F}; + case 0x1E3C: + return new int[] {0x1E3D}; + case 0x1E38: + return new int[] {0x1E39}; + case 0x33D7: + return new int[] {0x0070, 0x0068}; + case 0x050A: + return new int[] {0x050B}; + case 0x1D4D1: + return new int[] {0x0062}; + case 0x1D4D2: + return new int[] {0x0063}; + case 0x20A8: + return new int[] {0x0072, 0x0073}; + case 0x33D9: + return new int[] {0x0070, 0x0070, 0x006D}; + case 0x1D4D0: + return new int[] {0x0061}; + case 0x1D4D5: + return new int[] {0x0066}; + case 0x0506: + return new int[] {0x0507}; + case 0x1D4D6: + return new int[] {0x0067}; + case 0x1D4D3: + return new int[] {0x0064}; + case 0x0504: + return new int[] {0x0505}; + case 0x1D4D4: + return new int[] {0x0065}; + case 0x1D4D9: + return new int[] {0x006A}; + case 0x1D4D7: + return new int[] {0x0068}; + case 0x0508: + return new int[] {0x0509}; + case 0x1D4D8: + return new int[] {0x0069}; + case 0x33CE: + return new int[] {0x006B, 0x006D}; + case 0x33CD: + return new int[] {0x006B, 0x006B}; + case 0x1D4DA: + return new int[] {0x006B}; + case 0x0502: + return new int[] {0x0503}; + case 0x1D4DB: + return new int[] {0x006C}; + case 0x0500: + return new int[] {0x0501}; + case 0x1D4DE: + return new int[] {0x006F}; + case 0x1D4DF: + return new int[] {0x0070}; + case 0x1D4DC: + return new int[] {0x006D}; + case 0x1D4DD: + return new int[] {0x006E}; + case 0x33CB: + return new int[] {0x0068, 0x0070}; + case 0x1D4E2: + return new int[] {0x0073}; + case 0x1D4E3: + return new int[] {0x0074}; + case 0x1D4E0: + return new int[] {0x0071}; + case 0x1D4E1: + return new int[] {0x0072}; + case 0x1D4E6: + return new int[] {0x0077}; + case 0x1D4E7: + return new int[] {0x0078}; + case 0x1D4E4: + return new int[] {0x0075}; + case 0x1D4E5: + return new int[] {0x0076}; + case 0x1D4E8: + return new int[] {0x0079}; + case 0x1D4E9: + return new int[] {0x007A}; + case 0x33DD: + return new int[] {0x0077, 0x0062}; + case 0x050E: + return new int[] {0x050F}; + case 0x050C: + return new int[] {0x050D}; + case 0x33DC: + return new int[] {0x0073, 0x0076}; + case 0x33DA: + return new int[] {0x0070, 0x0072}; + case 0xFF30: + return new int[] {0xFF50}; + case 0xFF31: + return new int[] {0xFF51}; + case 0xFF32: + return new int[] {0xFF52}; + case 0x1D6F1: + return new int[] {0x03C0}; + case 0x1D4B0: + return new int[] {0x0075}; + case 0x1D6F2: + return new int[] {0x03C1}; + case 0x1D6F0: + return new int[] {0x03BF}; + case 0xFF37: + return new int[] {0xFF57}; + case 0x1D4B3: + return new int[] {0x0078}; + case 0x1D6F5: + return new int[] {0x03C4}; + case 0xFF38: + return new int[] {0xFF58}; + case 0x1D4B4: + return new int[] {0x0079}; + case 0x1D6F6: + return new int[] {0x03C5}; + case 0xFF39: + return new int[] {0xFF59}; + case 0x1D4B1: + return new int[] {0x0076}; + case 0x1D6F3: + return new int[] {0x03B8}; + case 0x1D4B2: + return new int[] {0x0077}; + case 0x1D6F4: + return new int[] {0x03C3}; + case 0xFF33: + return new int[] {0xFF53}; + case 0x1D6F9: + return new int[] {0x03C8}; + case 0xFF34: + return new int[] {0xFF54}; + case 0xFF35: + return new int[] {0xFF55}; + case 0x1D4B5: + return new int[] {0x007A}; + case 0x1D6F7: + return new int[] {0x03C6}; + case 0xFF36: + return new int[] {0xFF56}; + case 0x1D6F8: + return new int[] {0x03C7}; + case 0xFF3A: + return new int[] {0xFF5A}; + case 0x1D6FA: + return new int[] {0x03C9}; + case 0x053A: + return new int[] {0x056A}; + case 0xFF21: + return new int[] {0xFF41}; + case 0x053D: + return new int[] {0x056D}; + case 0x1E02: + return new int[] {0x1E03}; + case 0x053E: + return new int[] {0x056E}; + case 0x053B: + return new int[] {0x056B}; + case 0x1E00: + return new int[] {0x1E01}; + case 0x053C: + return new int[] {0x056C}; + case 0x0538: + return new int[] {0x0568}; + case 0xFF26: + return new int[] {0xFF46}; + case 0x0539: + return new int[] {0x0569}; + case 0xFF27: + return new int[] {0xFF47}; + case 0x0536: + return new int[] {0x0566}; + case 0xFF28: + return new int[] {0xFF48}; + case 0x0537: + return new int[] {0x0567}; + case 0xFF29: + return new int[] {0xFF49}; + case 0xFF22: + return new int[] {0xFF42}; + case 0xFF23: + return new int[] {0xFF43}; + case 0xFF24: + return new int[] {0xFF44}; + case 0xFF25: + return new int[] {0xFF45}; + case 0x0531: + return new int[] {0x0561}; + case 0xFF2A: + return new int[] {0xFF4A}; + case 0x0534: + return new int[] {0x0564}; + case 0x0535: + return new int[] {0x0565}; + case 0x0532: + return new int[] {0x0562}; + case 0x0533: + return new int[] {0x0563}; + case 0xFF2F: + return new int[] {0xFF4F}; + case 0xFF2B: + return new int[] {0xFF4B}; + case 0xFF2C: + return new int[] {0xFF4C}; + case 0xFF2D: + return new int[] {0xFF4D}; + case 0xFF2E: + return new int[] {0xFF4E}; + case 0x014E: + return new int[] {0x014F}; + case 0x1E97: + return new int[] {0x0074, 0x0308}; + case 0x1E98: + return new int[] {0x0077, 0x030A}; + case 0x014C: + return new int[] {0x014D}; + case 0x038E: + return new int[] {0x03CD}; + case 0x038F: + return new int[] {0x03CE}; + case 0x1E96: + return new int[] {0x0068, 0x0331}; + case 0x1E99: + return new int[] {0x0079, 0x030A}; + case 0x1E90: + return new int[] {0x1E91}; + case 0x1D63C: + return new int[] {0x0061}; + case 0x014A: + return new int[] {0x014B}; + case 0x038C: + return new int[] {0x03CC}; + case 0x1D63F: + return new int[] {0x0064}; + case 0x1E94: + return new int[] {0x1E95}; + case 0x038A: + return new int[] {0x03AF}; + case 0x1D63D: + return new int[] {0x0062}; + case 0x1E92: + return new int[] {0x1E93}; + case 0x1D63E: + return new int[] {0x0063}; + case 0x0145: + return new int[] {0x0146}; + case 0x0388: + return new int[] {0x03AD}; + case 0x0143: + return new int[] {0x0144}; + case 0x0386: + return new int[] {0x03AC}; + case 0x1E8E: + return new int[] {0x1E8F}; + case 0x0149: + return new int[] {0x02BC, 0x006E}; + case 0x1D640: + return new int[] {0x0065}; + case 0x0147: + return new int[] {0x0148}; + case 0x0389: + return new int[] {0x03AE}; + case 0x1D401: + return new int[] {0x0062}; + case 0x1D643: + return new int[] {0x0068}; + case 0x1D402: + return new int[] {0x0063}; + case 0x1D644: + return new int[] {0x0069}; + case 0x1D641: + return new int[] {0x0066}; + case 0x1D400: + return new int[] {0x0061}; + case 0x1D642: + return new int[] {0x0067}; + case 0x0141: + return new int[] {0x0142}; + case 0x1D405: + return new int[] {0x0066}; + case 0x1D647: + return new int[] {0x006C}; + case 0x1E8C: + return new int[] {0x1E8D}; + case 0x1D406: + return new int[] {0x0067}; + case 0x1D648: + return new int[] {0x006D}; + case 0x1D403: + return new int[] {0x0064}; + case 0x1D645: + return new int[] {0x006A}; + case 0x1E8A: + return new int[] {0x1E8B}; + case 0x1D404: + return new int[] {0x0065}; + case 0x1D646: + return new int[] {0x006B}; + case 0x1D409: + return new int[] {0x006A}; + case 0x039F: + return new int[] {0x03BF}; + case 0x1D407: + return new int[] {0x0068}; + case 0x1D649: + return new int[] {0x006E}; + case 0x015E: + return new int[] {0x015F}; + case 0x1D408: + return new int[] {0x0069}; + case 0x1D40A: + return new int[] {0x006B}; + case 0x1D64C: + return new int[] {0x0071}; + case 0x039A: + return new int[] {0x03BA}; + case 0x1D40B: + return new int[] {0x006C}; + case 0x1D64D: + return new int[] {0x0072}; + case 0x1D64A: + return new int[] {0x006F}; + case 0x1D64B: + return new int[] {0x0070}; + case 0x039D: + return new int[] {0x03BD}; + case 0x1D40E: + return new int[] {0x006F}; + case 0x015C: + return new int[] {0x015D}; + case 0x039E: + return new int[] {0x03BE}; + case 0x1D40F: + return new int[] {0x0070}; + case 0x039B: + return new int[] {0x03BB}; + case 0x1D40C: + return new int[] {0x006D}; + case 0x1D64E: + return new int[] {0x0073}; + case 0x015A: + return new int[] {0x015B}; + case 0x039C: + return new int[] {0x03BC}; + case 0x1D40D: + return new int[] {0x006E}; + case 0x1D64F: + return new int[] {0x0074}; + case 0x0156: + return new int[] {0x0157}; + case 0x0398: + return new int[] {0x03B8}; + case 0x0399: + return new int[] {0x03B9}; + case 0x0154: + return new int[] {0x0155}; + case 0x0396: + return new int[] {0x03B6}; + case 0x0397: + return new int[] {0x03B7}; + case 0x1D650: + return new int[] {0x0075}; + case 0x1D651: + return new int[] {0x0076}; + case 0x0158: + return new int[] {0x0159}; + case 0x0390: + return new int[] {0x03B9, 0x0308, 0x0301}; + case 0x1D412: + return new int[] {0x0073}; + case 0x1D654: + return new int[] {0x0079}; + case 0x0391: + return new int[] {0x03B1}; + case 0x1D413: + return new int[] {0x0074}; + case 0x1D655: + return new int[] {0x007A}; + case 0x1D410: + return new int[] {0x0071}; + case 0x1D652: + return new int[] {0x0077}; + case 0x1D411: + return new int[] {0x0072}; + case 0x1D653: + return new int[] {0x0078}; + case 0x0152: + return new int[] {0x0153}; + case 0x0394: + return new int[] {0x03B4}; + case 0x1D416: + return new int[] {0x0077}; + case 0x0395: + return new int[] {0x03B5}; + case 0x1D417: + return new int[] {0x0078}; + case 0x0150: + return new int[] {0x0151}; + case 0x0392: + return new int[] {0x03B2}; + case 0x1E9A: + return new int[] {0x0061, 0x02BE}; + case 0x1D414: + return new int[] {0x0075}; + case 0x0393: + return new int[] {0x03B3}; + case 0x1E9B: + return new int[] {0x1E61}; + case 0x1D415: + return new int[] {0x0076}; + case 0x210D: + return new int[] {0x0068}; + case 0x1D618: + return new int[] {0x0071}; + case 0x210C: + return new int[] {0x0068}; + case 0x1D619: + return new int[] {0x0072}; + case 0x016E: + return new int[] {0x016F}; + case 0x210B: + return new int[] {0x0068}; + case 0x1D616: + return new int[] {0x006F}; + case 0x1D617: + return new int[] {0x0070}; + case 0x1D61A: + return new int[] {0x0073}; + case 0x2109: + return new int[] {0x00B0, 0x0066}; + case 0x016C: + return new int[] {0x016D}; + case 0x1D61D: + return new int[] {0x0076}; + case 0x1D61E: + return new int[] {0x0077}; + case 0x016A: + return new int[] {0x016B}; + case 0x1D61B: + return new int[] {0x0074}; + case 0x1D61C: + return new int[] {0x0075}; + case 0x0168: + return new int[] {0x0169}; + case 0x2103: + return new int[] {0x00B0, 0x0063}; + case 0x2102: + return new int[] {0x0063}; + case 0x1D61F: + return new int[] {0x0078}; + case 0x0166: + return new int[] {0x0167}; + case 0x2107: + return new int[] {0x025B}; + case 0x1D621: + return new int[] {0x007A}; + case 0x0160: + return new int[] {0x0161}; + case 0x1D620: + return new int[] {0x0079}; + case 0x0164: + return new int[] {0x0165}; + case 0x0162: + return new int[] {0x0163}; + case 0x211D: + return new int[] {0x0072}; + case 0x017F: + return new int[] {0x0073}; + case 0x211C: + return new int[] {0x0072}; + case 0x211B: + return new int[] {0x0072}; + case 0x017D: + return new int[] {0x017E}; + case 0x211A: + return new int[] {0x0071}; + case 0x017B: + return new int[] {0x017C}; + case 0x0178: + return new int[] {0x00FF}; + case 0x2115: + return new int[] {0x006E}; + case 0x0179: + return new int[] {0x017A}; + case 0x0176: + return new int[] {0x0177}; + case 0x2112: + return new int[] {0x006C}; + case 0x2119: + return new int[] {0x0070}; + case 0x2116: + return new int[] {0x006E, 0x006F}; + case 0x0170: + return new int[] {0x0171}; + case 0x0174: + return new int[] {0x0175}; + case 0x2111: + return new int[] {0x0069}; + case 0x2110: + return new int[] {0x0069}; + case 0x0172: + return new int[] {0x0173}; + case 0x010A: + return new int[] {0x010B}; + case 0x1E54: + return new int[] {0x1E55}; + case 0xFB13: + return new int[] {0x0574, 0x0576}; + case 0x1E52: + return new int[] {0x1E53}; + case 0xFB14: + return new int[] {0x0574, 0x0565}; + case 0x010E: + return new int[] {0x010F}; + case 0x1E58: + return new int[] {0x1E59}; + case 0x010C: + return new int[] {0x010D}; + case 0x1E56: + return new int[] {0x1E57}; + case 0x0108: + return new int[] {0x0109}; + case 0xFB15: + return new int[] {0x0574, 0x056B}; + case 0x1E50: + return new int[] {0x1E51}; + case 0xFB16: + return new int[] {0x057E, 0x0576}; + case 0xFB17: + return new int[] {0x0574, 0x056D}; + case 0x0102: + return new int[] {0x0103}; + case 0x1E4C: + return new int[] {0x1E4D}; + case 0x0100: + return new int[] {0x0101}; + case 0x1E4A: + return new int[] {0x1E4B}; + case 0x0106: + return new int[] {0x0107}; + case 0x0345: + return new int[] {0x03B9}; + case 0x0587: + return new int[] {0x0565, 0x0582}; + case 0x0104: + return new int[] {0x0105}; + case 0x1E4E: + return new int[] {0x1E4F}; + case 0x1E48: + return new int[] {0x1E49}; + case 0x1E64: + return new int[] {0x1E65}; + case 0xFB00: + return new int[] {0x0066, 0x0066}; + case 0x011C: + return new int[] {0x011D}; + case 0xFB01: + return new int[] {0x0066, 0x0069}; + case 0x1D608: + return new int[] {0x0061}; + case 0x1E62: + return new int[] {0x1E63}; + case 0xFB02: + return new int[] {0x0066, 0x006C}; + case 0x011A: + return new int[] {0x011B}; + case 0xFB03: + return new int[] {0x0066, 0x0066, 0x0069}; + case 0x1E68: + return new int[] {0x1E69}; + case 0x1E66: + return new int[] {0x1E67}; + case 0x1D609: + return new int[] {0x0062}; + case 0x011E: + return new int[] {0x011F}; + case 0x0118: + return new int[] {0x0119}; + case 0x1E60: + return new int[] {0x1E61}; + case 0xFB04: + return new int[] {0x0066, 0x0066, 0x006C}; + case 0x1D60C: + return new int[] {0x0065}; + case 0xFB05: + return new int[] {0x0073, 0x0074}; + case 0x1D60D: + return new int[] {0x0066}; + case 0xFB06: + return new int[] {0x0073, 0x0074}; + case 0x1D60A: + return new int[] {0x0063}; + case 0x1D60B: + return new int[] {0x0064}; + case 0x0112: + return new int[] {0x0113}; + case 0x1E5C: + return new int[] {0x1E5D}; + case 0x0110: + return new int[] {0x0111}; + case 0x1E5A: + return new int[] {0x1E5B}; + case 0x1D60E: + return new int[] {0x0067}; + case 0x1D60F: + return new int[] {0x0068}; + case 0x0116: + return new int[] {0x0117}; + case 0x0114: + return new int[] {0x0115}; + case 0x1E5E: + return new int[] {0x1E5F}; + case 0x1D610: + return new int[] {0x0069}; + case 0x1D611: + return new int[] {0x006A}; + case 0x1D614: + return new int[] {0x006D}; + case 0x1D615: + return new int[] {0x006E}; + case 0x1D612: + return new int[] {0x006B}; + case 0x1D613: + return new int[] {0x006C}; + case 0x012C: + return new int[] {0x012D}; + case 0x1E76: + return new int[] {0x1E77}; + case 0x012A: + return new int[] {0x012B}; + case 0x1E74: + return new int[] {0x1E75}; + case 0x012E: + return new int[] {0x012F}; + case 0x1E78: + return new int[] {0x1E79}; + case 0x1E72: + return new int[] {0x1E73}; + case 0x1E70: + return new int[] {0x1E71}; + case 0x0124: + return new int[] {0x0125}; + case 0x1E6E: + return new int[] {0x1E6F}; + case 0x0122: + return new int[] {0x0123}; + case 0x1E6C: + return new int[] {0x1E6D}; + case 0x0128: + return new int[] {0x0129}; + case 0x0126: + return new int[] {0x0127}; + case 0x0120: + return new int[] {0x0121}; + case 0x1E6A: + return new int[] {0x1E6B}; + case 0x013D: + return new int[] {0x013E}; + case 0x1E86: + return new int[] {0x1E87}; + case 0x013B: + return new int[] {0x013C}; + case 0x1E84: + return new int[] {0x1E85}; + case 0x013F: + return new int[] {0x0140}; + case 0x1E88: + return new int[] {0x1E89}; + case 0x1E82: + return new int[] {0x1E83}; + case 0x1E80: + return new int[] {0x1E81}; + case 0x037A: + return new int[] {0x0020, 0x03B9}; + case 0x0134: + return new int[] {0x0135}; + case 0x1E7E: + return new int[] {0x1E7F}; + case 0x0132: + return new int[] {0x0133}; + case 0x1E7C: + return new int[] {0x1E7D}; + case 0x0139: + return new int[] {0x013A}; + case 0x0136: + return new int[] {0x0137}; + case 0x0130: + return new int[] {0x0069, 0x0307}; + case 0x1E7A: + return new int[] {0x1E7B}; + case 0x03A0: + return new int[] {0x03C0}; + case 0x03A1: + return new int[] {0x03C1}; + case 0x1D47A: + return new int[] {0x0073}; + case 0x03A4: + return new int[] {0x03C4}; + case 0x1EAC: + return new int[] {0x1EAD}; + case 0x1D47D: + return new int[] {0x0076}; + case 0x03A5: + return new int[] {0x03C5}; + case 0x1D47E: + return new int[] {0x0077}; + case 0x1EAA: + return new int[] {0x1EAB}; + case 0x1D47B: + return new int[] {0x0074}; + case 0x03A3: + return new int[] {0x03C3}; + case 0x1D47C: + return new int[] {0x0075}; + case 0x216B: + return new int[] {0x217B}; + case 0x1EA8: + return new int[] {0x1EA9}; + case 0x216A: + return new int[] {0x217A}; + case 0x10425: + return new int[] {0x1044D}; + case 0x1D47F: + return new int[] {0x0078}; + case 0x1EA6: + return new int[] {0x1EA7}; + case 0x216F: + return new int[] {0x217F}; + case 0x216E: + return new int[] {0x217E}; + case 0x216D: + return new int[] {0x217D}; + case 0x216C: + return new int[] {0x217C}; + case 0x1D481: + return new int[] {0x007A}; + case 0x1EA0: + return new int[] {0x1EA1}; + case 0x2169: + return new int[] {0x2179}; + case 0x2168: + return new int[] {0x2178}; + case 0x10420: + return new int[] {0x10448}; + case 0x2167: + return new int[] {0x2177}; + case 0x1D480: + return new int[] {0x0079}; + case 0x10422: + return new int[] {0x1044A}; + case 0x1EA4: + return new int[] {0x1EA5}; + case 0x10421: + return new int[] {0x10449}; + case 0x10424: + return new int[] {0x1044C}; + case 0x1EA2: + return new int[] {0x1EA3}; + case 0x10423: + return new int[] {0x1044B}; + case 0x2162: + return new int[] {0x2172}; + case 0x1041E: + return new int[] {0x10446}; + case 0x2161: + return new int[] {0x2171}; + case 0x1041D: + return new int[] {0x10445}; + case 0x2160: + return new int[] {0x2170}; + case 0x1041F: + return new int[] {0x10447}; + case 0x2166: + return new int[] {0x2176}; + case 0x2165: + return new int[] {0x2175}; + case 0x2164: + return new int[] {0x2174}; + case 0x2163: + return new int[] {0x2173}; + case 0x1EBA: + return new int[] {0x1EBB}; + case 0x03B0: + return new int[] {0x03C5, 0x0308, 0x0301}; + case 0x1041A: + return new int[] {0x10442}; + case 0x1EBE: + return new int[] {0x1EBF}; + case 0x1041C: + return new int[] {0x10444}; + case 0x1EBC: + return new int[] {0x1EBD}; + case 0x1041B: + return new int[] {0x10443}; + case 0x1EB8: + return new int[] {0x1EB9}; + case 0x10415: + return new int[] {0x1043D}; + case 0x10414: + return new int[] {0x1043C}; + case 0x1EB6: + return new int[] {0x1EB7}; + case 0x10417: + return new int[] {0x1043F}; + case 0x10416: + return new int[] {0x1043E}; + case 0x10419: + return new int[] {0x10441}; + case 0x10418: + return new int[] {0x10440}; + case 0x1EB0: + return new int[] {0x1EB1}; + case 0x03AA: + return new int[] {0x03CA}; + case 0x1EB4: + return new int[] {0x1EB5}; + case 0x10411: + return new int[] {0x10439}; + case 0x10410: + return new int[] {0x10438}; + case 0x03AB: + return new int[] {0x03CB}; + case 0x1EB2: + return new int[] {0x1EB3}; + case 0x10413: + return new int[] {0x1043B}; + case 0x10412: + return new int[] {0x1043A}; + case 0x03A8: + return new int[] {0x03C8}; + case 0x1040D: + return new int[] {0x10435}; + case 0x03A9: + return new int[] {0x03C9}; + case 0x1040C: + return new int[] {0x10434}; + case 0x03A6: + return new int[] {0x03C6}; + case 0x1EAE: + return new int[] {0x1EAF}; + case 0x1040F: + return new int[] {0x10437}; + case 0x03A7: + return new int[] {0x03C7}; + case 0x1040E: + return new int[] {0x10436}; + case 0x03C2: + return new int[] {0x03C3}; + case 0x1ECA: + return new int[] {0x1ECB}; + case 0x1ECE: + return new int[] {0x1ECF}; + case 0x1ECC: + return new int[] {0x1ECD}; + case 0x1EC8: + return new int[] {0x1EC9}; + case 0x1EC2: + return new int[] {0x1EC3}; + case 0x1EC0: + return new int[] {0x1EC1}; + case 0x1EC6: + return new int[] {0x1EC7}; + case 0x1EC4: + return new int[] {0x1EC5}; + case 0x1D468: + return new int[] {0x0061}; + case 0x1D469: + return new int[] {0x0062}; + case 0x03D3: + return new int[] {0x03CD}; + case 0x03D4: + return new int[] {0x03CB}; + case 0x1EDC: + return new int[] {0x1EDD}; + case 0x03D1: + return new int[] {0x03B8}; + case 0x03D2: + return new int[] {0x03C5}; + case 0x1EDA: + return new int[] {0x1EDB}; + case 0x1D46C: + return new int[] {0x0065}; + case 0x03D8: + return new int[] {0x03D9}; + case 0x1D46D: + return new int[] {0x0066}; + case 0x03D5: + return new int[] {0x03C6}; + case 0x1D46A: + return new int[] {0x0063}; + case 0x03D6: + return new int[] {0x03C0}; + case 0x1EDE: + return new int[] {0x1EDF}; + case 0x1D46B: + return new int[] {0x0064}; + case 0x1ED8: + return new int[] {0x1ED9}; + case 0x1D46E: + return new int[] {0x0067}; + case 0x1D46F: + return new int[] {0x0068}; + case 0x03D0: + return new int[] {0x03B2}; + case 0x1ED2: + return new int[] {0x1ED3}; + case 0x1D470: + return new int[] {0x0069}; + case 0x1D471: + return new int[] {0x006A}; + case 0x1ED0: + return new int[] {0x1ED1}; + case 0x1ED6: + return new int[] {0x1ED7}; + case 0x1D474: + return new int[] {0x006D}; + case 0x1D475: + return new int[] {0x006E}; + case 0x1ED4: + return new int[] {0x1ED5}; + case 0x1D472: + return new int[] {0x006B}; + case 0x1D473: + return new int[] {0x006C}; + case 0x1D478: + return new int[] {0x0071}; + case 0x1D479: + return new int[] {0x0072}; + case 0x1D476: + return new int[] {0x006F}; + case 0x1D477: + return new int[] {0x0070}; + case 0x212D: + return new int[] {0x0063}; + case 0x212C: + return new int[] {0x0062}; + case 0x1D67B: + return new int[] {0x006C}; + case 0x1D43A: + return new int[] {0x0067}; + case 0x1D67C: + return new int[] {0x006D}; + case 0x1D67A: + return new int[] {0x006B}; + case 0x018A: + return new int[] {0x0257}; + case 0x1D43D: + return new int[] {0x006A}; + case 0x1D67F: + return new int[] {0x0070}; + case 0x018B: + return new int[] {0x018C}; + case 0x1D43E: + return new int[] {0x006B}; + case 0x1D43B: + return new int[] {0x0068}; + case 0x1D67D: + return new int[] {0x006E}; + case 0x1D43C: + return new int[] {0x0069}; + case 0x1D67E: + return new int[] {0x006F}; + case 0x018E: + return new int[] {0x01DD}; + case 0x212B: + return new int[] {0x00E5}; + case 0x018F: + return new int[] {0x0259}; + case 0x212A: + return new int[] {0x006B}; + case 0x1D43F: + return new int[] {0x006C}; + case 0x0189: + return new int[] {0x0256}; + case 0x2126: + return new int[] {0x03C9}; + case 0x1D680: + return new int[] {0x0071}; + case 0x0187: + return new int[] {0x0188}; + case 0x2124: + return new int[] {0x007A}; + case 0x1D441: + return new int[] {0x006E}; + case 0x1D683: + return new int[] {0x0074}; + case 0x1D442: + return new int[] {0x006F}; + case 0x1D684: + return new int[] {0x0075}; + case 0x2128: + return new int[] {0x007A}; + case 0x1D681: + return new int[] {0x0072}; + case 0x1D440: + return new int[] {0x006D}; + case 0x1D682: + return new int[] {0x0073}; + case 0x0181: + return new int[] {0x0253}; + case 0x1D445: + return new int[] {0x0072}; + case 0x1D687: + return new int[] {0x0078}; + case 0x0182: + return new int[] {0x0183}; + case 0x1D446: + return new int[] {0x0073}; + case 0x1D688: + return new int[] {0x0079}; + case 0x1D443: + return new int[] {0x0070}; + case 0x1D685: + return new int[] {0x0076}; + case 0x1D444: + return new int[] {0x0071}; + case 0x1D686: + return new int[] {0x0077}; + case 0x2122: + return new int[] {0x0074, 0x006D}; + case 0x1D449: + return new int[] {0x0076}; + case 0x0186: + return new int[] {0x0254}; + case 0x2121: + return new int[] {0x0074, 0x0065, 0x006C}; + case 0x2120: + return new int[] {0x0073, 0x006D}; + case 0x1D447: + return new int[] {0x0074}; + case 0x1D689: + return new int[] {0x007A}; + case 0x0184: + return new int[] {0x0185}; + case 0x1D448: + return new int[] {0x0075}; + case 0x213F: + return new int[] {0x03C0}; + case 0x213E: + return new int[] {0x03B3}; + case 0x1D44A: + return new int[] {0x0077}; + case 0x1D44B: + return new int[] {0x0078}; + case 0x019C: + return new int[] {0x026F}; + case 0x1D44C: + return new int[] {0x0079}; + case 0x1D44D: + return new int[] {0x007A}; + case 0x019F: + return new int[] {0x0275}; + case 0x019D: + return new int[] {0x0272}; + case 0x0198: + return new int[] {0x0199}; + case 0x0193: + return new int[] {0x0260}; + case 0x0190: + return new int[] {0x025B}; + case 0x0191: + return new int[] {0x0192}; + case 0x0196: + return new int[] {0x0269}; + case 0x2133: + return new int[] {0x006D}; + case 0x0197: + return new int[] {0x0268}; + case 0x0194: + return new int[] {0x0263}; + case 0x2131: + return new int[] {0x0066}; + case 0x2130: + return new int[] {0x0065}; + case 0x1D418: + return new int[] {0x0079}; + case 0x1D419: + return new int[] {0x007A}; + case 0x1040B: + return new int[] {0x10433}; + case 0x1040A: + return new int[] {0x10432}; + case 0x10404: + return new int[] {0x1042C}; + case 0x10403: + return new int[] {0x1042B}; + case 0x10406: + return new int[] {0x1042E}; + case 0x10405: + return new int[] {0x1042D}; + case 0x10408: + return new int[] {0x10430}; + case 0x10407: + return new int[] {0x1042F}; + case 0x10409: + return new int[] {0x10431}; + case 0x2145: + return new int[] {0x0064}; + case 0x10400: + return new int[] {0x10428}; + case 0x10402: + return new int[] {0x1042A}; + case 0x10401: + return new int[] {0x10429}; + case 0x1D672: + return new int[] {0x0063}; + case 0x1D673: + return new int[] {0x0064}; + case 0x1D670: + return new int[] {0x0061}; + case 0x1D671: + return new int[] {0x0062}; + case 0x1D434: + return new int[] {0x0061}; + case 0x1D676: + return new int[] {0x0067}; + case 0x1D435: + return new int[] {0x0062}; + case 0x1D677: + return new int[] {0x0068}; + case 0x1D674: + return new int[] {0x0065}; + case 0x1D675: + return new int[] {0x0066}; + case 0x1D438: + return new int[] {0x0065}; + case 0x1D439: + return new int[] {0x0066}; + case 0x1D436: + return new int[] {0x0063}; + case 0x1D678: + return new int[] {0x0069}; + case 0x1D437: + return new int[] {0x0064}; + case 0x1D679: + return new int[] {0x006A}; + case 0x01E6: + return new int[] {0x01E7}; + case 0x01E4: + return new int[] {0x01E5}; + case 0x01E8: + return new int[] {0x01E9}; + case 0x1D5B2: + return new int[] {0x0073}; + case 0x1D5B3: + return new int[] {0x0074}; + case 0x1D5B0: + return new int[] {0x0071}; + case 0x1D5B1: + return new int[] {0x0072}; + case 0x01E2: + return new int[] {0x01E3}; + case 0x1D5B6: + return new int[] {0x0077}; + case 0x1D5B7: + return new int[] {0x0078}; + case 0x01E0: + return new int[] {0x01E1}; + case 0x1D5B4: + return new int[] {0x0075}; + case 0x1D5B5: + return new int[] {0x0076}; + case 0x01DE: + return new int[] {0x01DF}; + case 0x1D5B8: + return new int[] {0x0079}; + case 0x1D5B9: + return new int[] {0x007A}; + case 0x01DB: + return new int[] {0x01DC}; + case 0x01F7: + return new int[] {0x01BF}; + case 0x01F8: + return new int[] {0x01F9}; + case 0x01F6: + return new int[] {0x0195}; + case 0x01F0: + return new int[] {0x006A, 0x030C}; + case 0x01F4: + return new int[] {0x01F5}; + case 0x01F1: + return new int[] {0x01F3}; + case 0x01F2: + return new int[] {0x01F3}; + case 0x01EE: + return new int[] {0x01EF}; + case 0x01EC: + return new int[] {0x01ED}; + case 0x01EA: + return new int[] {0x01EB}; + case 0x01FE: + return new int[] {0x01FF}; + case 0x01FC: + return new int[] {0x01FD}; + case 0x01FA: + return new int[] {0x01FB}; + case 0x1D5A1: + return new int[] {0x0062}; + case 0x1D5A2: + return new int[] {0x0063}; + case 0x1D5A0: + return new int[] {0x0061}; + case 0x1D5A5: + return new int[] {0x0066}; + case 0x1D5A6: + return new int[] {0x0067}; + case 0x1D5A3: + return new int[] {0x0064}; + case 0x1D5A4: + return new int[] {0x0065}; + case 0x1D5A9: + return new int[] {0x006A}; + case 0x1D5A7: + return new int[] {0x0068}; + case 0x1D5A8: + return new int[] {0x0069}; + case 0x1D5AA: + return new int[] {0x006B}; + case 0x1D5AB: + return new int[] {0x006C}; + case 0x1D5AE: + return new int[] {0x006F}; + case 0x1D5AF: + return new int[] {0x0070}; + case 0x1D5AC: + return new int[] {0x006D}; + case 0x1D5AD: + return new int[] {0x006E}; + case 0x01A2: + return new int[] {0x01A3}; + case 0x03E4: + return new int[] {0x03E5}; + case 0x1EEC: + return new int[] {0x1EED}; + case 0x01A0: + return new int[] {0x01A1}; + case 0x03E2: + return new int[] {0x03E3}; + case 0x1EEA: + return new int[] {0x1EEB}; + case 0x01A6: + return new int[] {0x0280}; + case 0x03E8: + return new int[] {0x03E9}; + case 0x01A7: + return new int[] {0x01A8}; + case 0x01A4: + return new int[] {0x01A5}; + case 0x03E6: + return new int[] {0x03E7}; + case 0x1EEE: + return new int[] {0x1EEF}; + case 0x03E0: + return new int[] {0x03E1}; + case 0x03DC: + return new int[] {0x03DD}; + case 0x1EE4: + return new int[] {0x1EE5}; + case 0x03DA: + return new int[] {0x03DB}; + case 0x1EE2: + return new int[] {0x1EE3}; + case 0x1EE8: + return new int[] {0x1EE9}; + case 0x03DE: + return new int[] {0x03DF}; + case 0x1EE6: + return new int[] {0x1EE7}; + case 0x1EE0: + return new int[] {0x1EE1}; + case 0x1D7BB: + return new int[] {0x03C3}; + case 0x01B3: + return new int[] {0x01B4}; + case 0x03F5: + return new int[] {0x03B5}; + case 0x01B1: + return new int[] {0x028A}; + case 0x01B2: + return new int[] {0x028B}; + case 0x03F4: + return new int[] {0x03B8}; + case 0x01B7: + return new int[] {0x0292}; + case 0x01B8: + return new int[] {0x01B9}; + case 0x01B5: + return new int[] {0x01B6}; + case 0x03F1: + return new int[] {0x03C1}; + case 0x03F2: + return new int[] {0x03C3}; + case 0x03F0: + return new int[] {0x03BA}; + case 0x1EF4: + return new int[] {0x1EF5}; + case 0x01AC: + return new int[] {0x01AD}; + case 0x03EE: + return new int[] {0x03EF}; + case 0x1EF2: + return new int[] {0x1EF3}; + case 0x03EC: + return new int[] {0x03ED}; + case 0x01AF: + return new int[] {0x01B0}; + case 0x1EF8: + return new int[] {0x1EF9}; + case 0x1EF6: + return new int[] {0x1EF7}; + case 0x01AE: + return new int[] {0x0288}; + case 0x01A9: + return new int[] {0x0283}; + case 0x1EF0: + return new int[] {0x1EF1}; + case 0x03EA: + return new int[] {0x03EB}; + case 0x01C4: + return new int[] {0x01C6}; + case 0x01C5: + return new int[] {0x01C6}; + case 0x01C8: + return new int[] {0x01C9}; + case 0x01C7: + return new int[] {0x01C9}; + case 0x01BC: + return new int[] {0x01BD}; + case 0x01D5: + return new int[] {0x01D6}; + case 0x01D3: + return new int[] {0x01D4}; + case 0x01D9: + return new int[] {0x01DA}; + case 0x01D7: + return new int[] {0x01D8}; + case 0x1D7A0: + return new int[] {0x03C1}; + case 0x01D1: + return new int[] {0x01D2}; + case 0x1D7A3: + return new int[] {0x03C4}; + case 0x1D7A4: + return new int[] {0x03C5}; + case 0x1D7A1: + return new int[] {0x03B8}; + case 0x1D7A2: + return new int[] {0x03C3}; + case 0x01CD: + return new int[] {0x01CE}; + case 0x1D7A7: + return new int[] {0x03C8}; + case 0x1D7A8: + return new int[] {0x03C9}; + case 0x01CB: + return new int[] {0x01CC}; + case 0x1D7A5: + return new int[] {0x03C6}; + case 0x1D7A6: + return new int[] {0x03C7}; + case 0x01CF: + return new int[] {0x01D0}; + case 0x01CA: + return new int[] {0x01CC}; + case 0x042A: + return new int[] {0x044A}; + case 0x042D: + return new int[] {0x044D}; + case 0x042E: + return new int[] {0x044E}; + case 0x042B: + return new int[] {0x044B}; + case 0x042C: + return new int[] {0x044C}; + case 0x0428: + return new int[] {0x0448}; + case 0x0429: + return new int[] {0x0449}; + case 0x0426: + return new int[] {0x0446}; + case 0x1F2E: + return new int[] {0x1F26}; + case 0x0427: + return new int[] {0x0447}; + case 0x1F2F: + return new int[] {0x1F27}; + case 0x0420: + return new int[] {0x0440}; + case 0x0421: + return new int[] {0x0441}; + case 0x0424: + return new int[] {0x0444}; + case 0x1F2C: + return new int[] {0x1F24}; + case 0x0425: + return new int[] {0x0445}; + case 0x1F2D: + return new int[] {0x1F25}; + case 0x0422: + return new int[] {0x0442}; + case 0x1F2A: + return new int[] {0x1F22}; + case 0x0423: + return new int[] {0x0443}; + case 0x1F2B: + return new int[] {0x1F23}; + case 0x1F28: + return new int[] {0x1F20}; + case 0x041E: + return new int[] {0x043E}; + case 0x041F: + return new int[] {0x043F}; + case 0x1F29: + return new int[] {0x1F21}; + case 0x1F3F: + return new int[] {0x1F37}; + case 0x1F3A: + return new int[] {0x1F32}; + case 0x1F3D: + return new int[] {0x1F35}; + case 0x1F3E: + return new int[] {0x1F36}; + case 0x1F3B: + return new int[] {0x1F33}; + case 0x1F3C: + return new int[] {0x1F34}; + case 0x1F38: + return new int[] {0x1F30}; + case 0x1F39: + return new int[] {0x1F31}; + case 0x042F: + return new int[] {0x044F}; + case 0x1F52: + return new int[] {0x03C5, 0x0313, 0x0300}; + case 0x020A: + return new int[] {0x020B}; + case 0x1F50: + return new int[] {0x03C5, 0x0313}; + case 0x1F56: + return new int[] {0x03C5, 0x0313, 0x0342}; + case 0x020E: + return new int[] {0x020F}; + case 0x1F54: + return new int[] {0x03C5, 0x0313, 0x0301}; + case 0x020C: + return new int[] {0x020D}; + case 0x0208: + return new int[] {0x0209}; + case 0x0206: + return new int[] {0x0207}; + case 0x0200: + return new int[] {0x0201}; + case 0x1F4A: + return new int[] {0x1F42}; + case 0x1F4B: + return new int[] {0x1F43}; + case 0x0204: + return new int[] {0x0205}; + case 0x0202: + return new int[] {0x0203}; + case 0x1F4C: + return new int[] {0x1F44}; + case 0x1F4D: + return new int[] {0x1F45}; + case 0x1F49: + return new int[] {0x1F41}; + case 0x1F48: + return new int[] {0x1F40}; + case 0x021A: + return new int[] {0x021B}; + case 0x021E: + return new int[] {0x021F}; + case 0x1F68: + return new int[] {0x1F60}; + case 0x021C: + return new int[] {0x021D}; + case 0x0218: + return new int[] {0x0219}; + case 0x1F5B: + return new int[] {0x1F53}; + case 0x0212: + return new int[] {0x0213}; + case 0x0210: + return new int[] {0x0211}; + case 0x1F5F: + return new int[] {0x1F57}; + case 0x0216: + return new int[] {0x0217}; + case 0x1F5D: + return new int[] {0x1F55}; + case 0x0214: + return new int[] {0x0215}; + case 0x1F59: + return new int[] {0x1F51}; + case 0x040B: + return new int[] {0x045B}; + case 0x040C: + return new int[] {0x045C}; + case 0x040A: + return new int[] {0x045A}; + case 0x0406: + return new int[] {0x0456}; + case 0x1F0E: + return new int[] {0x1F06}; + case 0x1D5D4: + return new int[] {0x0061}; + case 0x0407: + return new int[] {0x0457}; + case 0x1F0F: + return new int[] {0x1F07}; + case 0x1D5D5: + return new int[] {0x0062}; + case 0x0404: + return new int[] {0x0454}; + case 0x1F0C: + return new int[] {0x1F04}; + case 0x0405: + return new int[] {0x0455}; + case 0x1F0D: + return new int[] {0x1F05}; + case 0x1D5D8: + return new int[] {0x0065}; + case 0x1D5D9: + return new int[] {0x0066}; + case 0x0408: + return new int[] {0x0458}; + case 0x1D5D6: + return new int[] {0x0063}; + case 0x0409: + return new int[] {0x0459}; + case 0x1D5D7: + return new int[] {0x0064}; + case 0x0402: + return new int[] {0x0452}; + case 0x1F0A: + return new int[] {0x1F02}; + case 0x0403: + return new int[] {0x0453}; + case 0x1F0B: + return new int[] {0x1F03}; + case 0x1D5DA: + return new int[] {0x0067}; + case 0x0400: + return new int[] {0x0450}; + case 0x0401: + return new int[] {0x0451}; + case 0x1D5DD: + return new int[] {0x006A}; + case 0x1D5DE: + return new int[] {0x006B}; + case 0x1D5DB: + return new int[] {0x0068}; + case 0x1D5DC: + return new int[] {0x0069}; + case 0x1F09: + return new int[] {0x1F01}; + case 0x1D5DF: + return new int[] {0x006C}; + case 0x1F08: + return new int[] {0x1F00}; + case 0x041C: + return new int[] {0x043C}; + case 0x1D5E1: + return new int[] {0x006E}; + case 0x041D: + return new int[] {0x043D}; + case 0x1D5E2: + return new int[] {0x006F}; + case 0x041A: + return new int[] {0x043A}; + case 0x041B: + return new int[] {0x043B}; + case 0x1D5E0: + return new int[] {0x006D}; + case 0x0417: + return new int[] {0x0437}; + case 0x1D5E5: + return new int[] {0x0072}; + case 0x0418: + return new int[] {0x0438}; + case 0x1D5E6: + return new int[] {0x0073}; + case 0x0415: + return new int[] {0x0435}; + case 0x1F1D: + return new int[] {0x1F15}; + case 0x1D5E3: + return new int[] {0x0070}; + case 0x0416: + return new int[] {0x0436}; + case 0x1D5E4: + return new int[] {0x0071}; + case 0x1D5E9: + return new int[] {0x0076}; + case 0x0419: + return new int[] {0x0439}; + case 0x1D5E7: + return new int[] {0x0074}; + case 0x1D5E8: + return new int[] {0x0075}; + case 0x0410: + return new int[] {0x0430}; + case 0x0413: + return new int[] {0x0433}; + case 0x1F1B: + return new int[] {0x1F13}; + case 0x1D5EA: + return new int[] {0x0077}; + case 0x0414: + return new int[] {0x0434}; + case 0x1F1C: + return new int[] {0x1F14}; + case 0x1D5EB: + return new int[] {0x0078}; + case 0x0411: + return new int[] {0x0431}; + case 0x0412: + return new int[] {0x0432}; + case 0x1F1A: + return new int[] {0x1F12}; + case 0x040F: + return new int[] {0x045F}; + case 0x040D: + return new int[] {0x045D}; + case 0x1D5EC: + return new int[] {0x0079}; + case 0x040E: + return new int[] {0x045E}; + case 0x1D5ED: + return new int[] {0x007A}; + case 0x1F18: + return new int[] {0x1F10}; + case 0x1F19: + return new int[] {0x1F11}; + case 0x1D519: + return new int[] {0x0076}; + case 0x1D517: + return new int[] {0x0074}; + case 0x1D759: + return new int[] {0x03B4}; + case 0x1D518: + return new int[] {0x0075}; + case 0x1D51A: + return new int[] {0x0077}; + case 0x1D75C: + return new int[] {0x03B7}; + case 0x1D51B: + return new int[] {0x0078}; + case 0x1D75D: + return new int[] {0x03B8}; + case 0x1D75A: + return new int[] {0x03B5}; + case 0x1D75B: + return new int[] {0x03B6}; + case 0x1D51C: + return new int[] {0x0079}; + case 0x1D75E: + return new int[] {0x03B9}; + case 0x1D75F: + return new int[] {0x03BA}; + case 0x1D760: + return new int[] {0x03BB}; + case 0x1D761: + return new int[] {0x03BC}; + case 0x1D764: + return new int[] {0x03BF}; + case 0x1D765: + return new int[] {0x03C0}; + case 0x1D762: + return new int[] {0x03BD}; + case 0x1D763: + return new int[] {0x03BE}; + case 0x1D768: + return new int[] {0x03C3}; + case 0x1D769: + return new int[] {0x03C4}; + case 0x1D766: + return new int[] {0x03C1}; + case 0x1D767: + return new int[] {0x03B8}; + case 0x1D76A: + return new int[] {0x03C5}; + case 0x1D76D: + return new int[] {0x03C8}; + case 0x1D76E: + return new int[] {0x03C9}; + case 0x1D76B: + return new int[] {0x03C6}; + case 0x1D76C: + return new int[] {0x03C7}; + case 0x1D538: + return new int[] {0x0061}; + case 0x004F: + return new int[] {0x006F}; + case 0x004D: + return new int[] {0x006D}; + case 0x004E: + return new int[] {0x006E}; + case 0x004B: + return new int[] {0x006B}; + case 0x004C: + return new int[] {0x006C}; + case 0x004A: + return new int[] {0x006A}; + case 0x0046: + return new int[] {0x0066}; + case 0x0047: + return new int[] {0x0067}; + case 0x0044: + return new int[] {0x0064}; + case 0x0045: + return new int[] {0x0065}; + case 0x0048: + return new int[] {0x0068}; + case 0x0049: + return new int[] {0x0069}; + case 0x0042: + return new int[] {0x0062}; + case 0x1D504: + return new int[] {0x0061}; + case 0x0043: + return new int[] {0x0063}; + case 0x1D505: + return new int[] {0x0062}; + case 0x1D747: + return new int[] {0x03C3}; + case 0x0041: + return new int[] {0x0061}; + case 0x1D508: + return new int[] {0x0065}; + case 0x1D509: + return new int[] {0x0066}; + case 0x1D507: + return new int[] {0x0064}; + case 0x1D50A: + return new int[] {0x0067}; + case 0x1D50D: + return new int[] {0x006A}; + case 0x1D50E: + return new int[] {0x006B}; + case 0x005A: + return new int[] {0x007A}; + case 0x0057: + return new int[] {0x0077}; + case 0x0058: + return new int[] {0x0078}; + case 0x0055: + return new int[] {0x0075}; + case 0x1D50F: + return new int[] {0x006C}; + case 0x0056: + return new int[] {0x0076}; + case 0x0059: + return new int[] {0x0079}; + case 0x1D511: + return new int[] {0x006E}; + case 0x0050: + return new int[] {0x0070}; + case 0x1D512: + return new int[] {0x006F}; + case 0x1D510: + return new int[] {0x006D}; + case 0x0053: + return new int[] {0x0073}; + case 0x1D757: + return new int[] {0x03B2}; + case 0x0054: + return new int[] {0x0074}; + case 0x1D516: + return new int[] {0x0073}; + case 0x1D758: + return new int[] {0x03B3}; + case 0x0051: + return new int[] {0x0071}; + case 0x1D513: + return new int[] {0x0070}; + case 0x0052: + return new int[] {0x0072}; + case 0x1D514: + return new int[] {0x0071}; + case 0x1D756: + return new int[] {0x03B1}; + case 0x022C: + return new int[] {0x022D}; + case 0x046E: + return new int[] {0x046F}; + case 0x022A: + return new int[] {0x022B}; + case 0x046C: + return new int[] {0x046D}; + case 0x022E: + return new int[] {0x022F}; + case 0x0228: + return new int[] {0x0229}; + case 0x1D71C: + return new int[] {0x03B1}; + case 0x046A: + return new int[] {0x046B}; + case 0x1D71D: + return new int[] {0x03B2}; + case 0x0222: + return new int[] {0x0223}; + case 0x0464: + return new int[] {0x0465}; + case 0x1F6C: + return new int[] {0x1F64}; + case 0x1F6D: + return new int[] {0x1F65}; + case 0x0220: + return new int[] {0x019E}; + case 0x0462: + return new int[] {0x0463}; + case 0x1F6A: + return new int[] {0x1F62}; + case 0x1D71E: + return new int[] {0x03B3}; + case 0x1F6B: + return new int[] {0x1F63}; + case 0x1D71F: + return new int[] {0x03B4}; + case 0x0226: + return new int[] {0x0227}; + case 0x0468: + return new int[] {0x0469}; + case 0x0224: + return new int[] {0x0225}; + case 0x0466: + return new int[] {0x0467}; + case 0x1F6E: + return new int[] {0x1F66}; + case 0x1F6F: + return new int[] {0x1F67}; + case 0x1D720: + return new int[] {0x03B5}; + case 0x1D721: + return new int[] {0x03B6}; + case 0x1F69: + return new int[] {0x1F61}; + case 0x0460: + return new int[] {0x0461}; + case 0x1D724: + return new int[] {0x03B9}; + case 0x1D725: + return new int[] {0x03BA}; + case 0x1D722: + return new int[] {0x03B7}; + case 0x1D723: + return new int[] {0x03B8}; + case 0x047E: + return new int[] {0x047F}; + case 0x1F85: + return new int[] {0x1F05, 0x03B9}; + case 0x1D728: + return new int[] {0x03BD}; + case 0x1F86: + return new int[] {0x1F06, 0x03B9}; + case 0x1D729: + return new int[] {0x03BE}; + case 0x047C: + return new int[] {0x047D}; + case 0x1F83: + return new int[] {0x1F03, 0x03B9}; + case 0x1D726: + return new int[] {0x03BB}; + case 0x1F84: + return new int[] {0x1F04, 0x03B9}; + case 0x1D727: + return new int[] {0x03BC}; + case 0x1F89: + return new int[] {0x1F01, 0x03B9}; + case 0x1F87: + return new int[] {0x1F07, 0x03B9}; + case 0x1F88: + return new int[] {0x1F00, 0x03B9}; + case 0x1D72A: + return new int[] {0x03BF}; + case 0x047A: + return new int[] {0x047B}; + case 0x1F81: + return new int[] {0x1F01, 0x03B9}; + case 0x1D72D: + return new int[] {0x03B8}; + case 0x1F82: + return new int[] {0x1F02, 0x03B9}; + case 0x1D72E: + return new int[] {0x03C3}; + case 0x1D72B: + return new int[] {0x03C0}; + case 0x1F80: + return new int[] {0x1F00, 0x03B9}; + case 0x1D72C: + return new int[] {0x03C1}; + case 0x0476: + return new int[] {0x0477}; + case 0x1D72F: + return new int[] {0x03C4}; + case 0x0232: + return new int[] {0x0233}; + case 0x0474: + return new int[] {0x0475}; + case 0x0478: + return new int[] {0x0479}; + case 0x1D731: + return new int[] {0x03C6}; + case 0x1D732: + return new int[] {0x03C7}; + case 0x1D730: + return new int[] {0x03C5}; + case 0x0230: + return new int[] {0x0231}; + case 0x0472: + return new int[] {0x0473}; + case 0x1D733: + return new int[] {0x03C8}; + case 0x0470: + return new int[] {0x0471}; + case 0x1D734: + return new int[] {0x03C9}; + case 0x1F96: + return new int[] {0x1F26, 0x03B9}; + case 0x1F97: + return new int[] {0x1F27, 0x03B9}; + case 0x1F94: + return new int[] {0x1F24, 0x03B9}; + case 0x048E: + return new int[] {0x048F}; + case 0x1F95: + return new int[] {0x1F25, 0x03B9}; + case 0x1F98: + return new int[] {0x1F20, 0x03B9}; + case 0x1F99: + return new int[] {0x1F21, 0x03B9}; + case 0x1F92: + return new int[] {0x1F22, 0x03B9}; + case 0x048C: + return new int[] {0x048D}; + case 0x1F93: + return new int[] {0x1F23, 0x03B9}; + case 0x1F90: + return new int[] {0x1F20, 0x03B9}; + case 0x048A: + return new int[] {0x048B}; + case 0x1F91: + return new int[] {0x1F21, 0x03B9}; + case 0x1F8E: + return new int[] {0x1F06, 0x03B9}; + case 0x1F8F: + return new int[] {0x1F07, 0x03B9}; + case 0x1F8C: + return new int[] {0x1F04, 0x03B9}; + case 0x1F8D: + return new int[] {0x1F05, 0x03B9}; + case 0x1F8A: + return new int[] {0x1F02, 0x03B9}; + case 0x1F8B: + return new int[] {0x1F03, 0x03B9}; + case 0x0480: + return new int[] {0x0481}; + case 0x049E: + return new int[] {0x049F}; + case 0x049C: + return new int[] {0x049D}; + case 0x049A: + return new int[] {0x049B}; + case 0x1F9F: + return new int[] {0x1F27, 0x03B9}; + case 0x0498: + return new int[] {0x0499}; + case 0x1F9D: + return new int[] {0x1F25, 0x03B9}; + case 0x1D70D: + return new int[] {0x03C3}; + case 0x0496: + return new int[] {0x0497}; + case 0x1F9E: + return new int[] {0x1F26, 0x03B9}; + case 0x0490: + return new int[] {0x0491}; + case 0x1F9B: + return new int[] {0x1F23, 0x03B9}; + case 0x0494: + return new int[] {0x0495}; + case 0x1F9C: + return new int[] {0x1F24, 0x03B9}; + case 0x0492: + return new int[] {0x0493}; + case 0x1F9A: + return new int[] {0x1F22, 0x03B9}; + case 0x04C1: + return new int[] {0x04C2}; + case 0x1FCA: + return new int[] {0x1F74}; + case 0x04C5: + return new int[] {0x04C6}; + case 0x04C3: + return new int[] {0x04C4}; + case 0x1FCB: + return new int[] {0x1F75}; + case 0x1FCC: + return new int[] {0x03B7, 0x03B9}; + case 0x1FC8: + return new int[] {0x1F72}; + case 0x1FC9: + return new int[] {0x1F73}; + case 0x1FC6: + return new int[] {0x03B7, 0x0342}; + case 0x1FC7: + return new int[] {0x03B7, 0x0342, 0x03B9}; + case 0x04BA: + return new int[] {0x04BB}; + case 0x1FC4: + return new int[] {0x03AE, 0x03B9}; + case 0x04BE: + return new int[] {0x04BF}; + case 0x1FC2: + return new int[] {0x1F74, 0x03B9}; + case 0x04BC: + return new int[] {0x04BD}; + case 0x1FC3: + return new int[] {0x03B7, 0x03B9}; + case 0x04B8: + return new int[] {0x04B9}; + case 0x3371: + return new int[] {0x0068, 0x0070, 0x0061}; + case 0x04B6: + return new int[] {0x04B7}; + case 0x1FBE: + return new int[] {0x03B9}; + case 0x3375: + return new int[] {0x006F, 0x0076}; + case 0x3373: + return new int[] {0x0061, 0x0075}; + case 0x04D2: + return new int[] {0x04D3}; + case 0x1FDA: + return new int[] {0x1F76}; + case 0x1FDB: + return new int[] {0x1F77}; + case 0x04D0: + return new int[] {0x04D1}; + case 0x04D6: + return new int[] {0x04D7}; + case 0x3390: + return new int[] {0x0068, 0x007A}; + case 0x04D4: + return new int[] {0x04D5}; + case 0x1FD9: + return new int[] {0x1FD1}; + case 0x338C: + return new int[] {0x03BC, 0x0066}; + case 0x338B: + return new int[] {0x006E, 0x0066}; + case 0x1FD7: + return new int[] {0x03B9, 0x0308, 0x0342}; + case 0x338A: + return new int[] {0x0070, 0x0066}; + case 0x1FD8: + return new int[] {0x1FD0}; + case 0x04CB: + return new int[] {0x04CC}; + case 0x1FD2: + return new int[] {0x03B9, 0x0308, 0x0300}; + case 0x1FD6: + return new int[] {0x03B9, 0x0342}; + case 0x1FD3: + return new int[] {0x03B9, 0x0308, 0x0301}; + case 0x04CD: + return new int[] {0x04CE}; + case 0x04C9: + return new int[] {0x04CA}; + case 0x3383: + return new int[] {0x006D, 0x0061}; + case 0x3382: + return new int[] {0x03BC, 0x0061}; + case 0x04C7: + return new int[] {0x04C8}; + case 0x3381: + return new int[] {0x006E, 0x0061}; + case 0x3380: + return new int[] {0x0070, 0x0061}; + case 0x3387: + return new int[] {0x0067, 0x0062}; + case 0x3386: + return new int[] {0x006D, 0x0062}; + case 0x3385: + return new int[] {0x006B, 0x0062}; + case 0x3384: + return new int[] {0x006B, 0x0061}; + case 0x1FEB: + return new int[] {0x1F7B}; + case 0x04E4: + return new int[] {0x04E5}; + case 0x1FEC: + return new int[] {0x1FE5}; + case 0x04E2: + return new int[] {0x04E3}; + case 0x1FEA: + return new int[] {0x1F7A}; + case 0x1D57C: + return new int[] {0x0071}; + case 0x04E8: + return new int[] {0x04E9}; + case 0x1D57D: + return new int[] {0x0072}; + case 0x1D57A: + return new int[] {0x006F}; + case 0x04E6: + return new int[] {0x04E7}; + case 0x1D57B: + return new int[] {0x0070}; + case 0x1FE8: + return new int[] {0x1FE0}; + case 0x1D57E: + return new int[] {0x0073}; + case 0x1FE9: + return new int[] {0x1FE1}; + case 0x1D57F: + return new int[] {0x0074}; + case 0x04E0: + return new int[] {0x04E1}; + case 0x1FE2: + return new int[] {0x03C5, 0x0308, 0x0300}; + case 0x1D580: + return new int[] {0x0075}; + case 0x04DC: + return new int[] {0x04DD}; + case 0x1FE3: + return new int[] {0x03C5, 0x0308, 0x0301}; + case 0x1D581: + return new int[] {0x0076}; + case 0x04DA: + return new int[] {0x04DB}; + case 0x1FE6: + return new int[] {0x03C5, 0x0342}; + case 0x1D584: + return new int[] {0x0079}; + case 0x1FE7: + return new int[] {0x03C5, 0x0308, 0x0342}; + case 0x1D585: + return new int[] {0x007A}; + case 0x1FE4: + return new int[] {0x03C1, 0x0313}; + case 0x1D582: + return new int[] {0x0077}; + case 0x04DE: + return new int[] {0x04DF}; + case 0x1D583: + return new int[] {0x0078}; + case 0x3394: + return new int[] {0x0074, 0x0068, 0x007A}; + case 0x3393: + return new int[] {0x0067, 0x0068, 0x007A}; + case 0x04D8: + return new int[] {0x04D9}; + case 0x3392: + return new int[] {0x006D, 0x0068, 0x007A}; + case 0x3391: + return new int[] {0x006B, 0x0068, 0x007A}; + case 0x04F4: + return new int[] {0x04F5}; + case 0x1FFC: + return new int[] {0x03C9, 0x03B9}; + case 0x04F2: + return new int[] {0x04F3}; + case 0x1FFA: + return new int[] {0x1F7C}; + case 0x1FFB: + return new int[] {0x1F7D}; + case 0x04F8: + return new int[] {0x04F9}; + case 0x1FF9: + return new int[] {0x1F79}; + case 0x04F0: + return new int[] {0x04F1}; + case 0x04EC: + return new int[] {0x04ED}; + case 0x1FF3: + return new int[] {0x03C9, 0x03B9}; + case 0x1FF4: + return new int[] {0x03CE, 0x03B9}; + case 0x04EA: + return new int[] {0x04EB}; + case 0x1FF2: + return new int[] {0x1F7C, 0x03B9}; + case 0x1FF7: + return new int[] {0x03C9, 0x0342, 0x03B9}; + case 0x1FF8: + return new int[] {0x1F78}; + case 0x04EE: + return new int[] {0x04EF}; + case 0x1FF6: + return new int[] {0x03C9, 0x0342}; + case 0x1D79C: + return new int[] {0x03BD}; + case 0x1D79D: + return new int[] {0x03BE}; + case 0x1D79A: + return new int[] {0x03BB}; + case 0x1D79B: + return new int[] {0x03BC}; + case 0x1D79E: + return new int[] {0x03BF}; + case 0x1D79F: + return new int[] {0x03C0}; + case 0x1D56C: + return new int[] {0x0061}; + case 0x1D56F: + return new int[] {0x0064}; + case 0x1D56D: + return new int[] {0x0062}; + case 0x1D56E: + return new int[] {0x0063}; + case 0x1D570: + return new int[] {0x0065}; + case 0x1D573: + return new int[] {0x0068}; + case 0x1D574: + return new int[] {0x0069}; + case 0x1D571: + return new int[] {0x0066}; + case 0x1D572: + return new int[] {0x0067}; + case 0x1D577: + return new int[] {0x006C}; + case 0x1D578: + return new int[] {0x006D}; + case 0x1D575: + return new int[] {0x006A}; + case 0x1D576: + return new int[] {0x006B}; + case 0x1D579: + return new int[] {0x006E}; + case 0x04A0: + return new int[] {0x04A1}; + case 0x1D539: + return new int[] {0x0062}; + case 0x1FAB: + return new int[] {0x1F63, 0x03B9}; + case 0x04A4: + return new int[] {0x04A5}; + case 0x1FAC: + return new int[] {0x1F64, 0x03B9}; + case 0x04A2: + return new int[] {0x04A3}; + case 0x1FAA: + return new int[] {0x1F62, 0x03B9}; + case 0x1FA6: + return new int[] {0x1F66, 0x03B9}; + case 0x1D53C: + return new int[] {0x0065}; + case 0x1FA7: + return new int[] {0x1F67, 0x03B9}; + case 0x1D53D: + return new int[] {0x0066}; + case 0x1FA4: + return new int[] {0x1F64, 0x03B9}; + case 0x1FA5: + return new int[] {0x1F65, 0x03B9}; + case 0x1D53B: + return new int[] {0x0064}; + case 0x1FA8: + return new int[] {0x1F60, 0x03B9}; + case 0x1D53E: + return new int[] {0x0067}; + case 0x1FA9: + return new int[] {0x1F61, 0x03B9}; + case 0x1FA2: + return new int[] {0x1F62, 0x03B9}; + case 0x1D540: + return new int[] {0x0069}; + case 0x1FA3: + return new int[] {0x1F63, 0x03B9}; + case 0x1D541: + return new int[] {0x006A}; + case 0x1FA0: + return new int[] {0x1F60, 0x03B9}; + case 0x1FA1: + return new int[] {0x1F61, 0x03B9}; + case 0x1D781: + return new int[] {0x03C3}; + case 0x1D544: + return new int[] {0x006D}; + case 0x1D542: + return new int[] {0x006B}; + case 0x1D543: + return new int[] {0x006C}; + case 0x1D546: + return new int[] {0x006F}; + case 0x04B0: + return new int[] {0x04B1}; + case 0x04B4: + return new int[] {0x04B5}; + case 0x1FBC: + return new int[] {0x03B1, 0x03B9}; + case 0x1D54A: + return new int[] {0x0073}; + case 0x04B2: + return new int[] {0x04B3}; + case 0x1FBA: + return new int[] {0x1F70}; + case 0x1FBB: + return new int[] {0x1F71}; + case 0x1FB7: + return new int[] {0x03B1, 0x0342, 0x03B9}; + case 0x1D54D: + return new int[] {0x0076}; + case 0x1FB8: + return new int[] {0x1FB0}; + case 0x1D54E: + return new int[] {0x0077}; + case 0x04AE: + return new int[] {0x04AF}; + case 0x1D54B: + return new int[] {0x0074}; + case 0x1FB6: + return new int[] {0x03B1, 0x0342}; + case 0x1D54C: + return new int[] {0x0075}; + case 0x1FB9: + return new int[] {0x1FB1}; + case 0x1D54F: + return new int[] {0x0078}; + case 0x1D790: + return new int[] {0x03B1}; + case 0x04AC: + return new int[] {0x04AD}; + case 0x1FB3: + return new int[] {0x03B1, 0x03B9}; + case 0x1D793: + return new int[] {0x03B4}; + case 0x1FB4: + return new int[] {0x03AC, 0x03B9}; + case 0x1D794: + return new int[] {0x03B5}; + case 0x04AA: + return new int[] {0x04AB}; + case 0x1D791: + return new int[] {0x03B2}; + case 0x1FB2: + return new int[] {0x1F70, 0x03B9}; + case 0x1D550: + return new int[] {0x0079}; + case 0x1D792: + return new int[] {0x03B3}; + case 0x1FAF: + return new int[] {0x1F67, 0x03B9}; + case 0x1D797: + return new int[] {0x03B8}; + case 0x04A8: + return new int[] {0x04A9}; + case 0x1D798: + return new int[] {0x03B9}; + case 0x1FAD: + return new int[] {0x1F65, 0x03B9}; + case 0x1D795: + return new int[] {0x03B6}; + case 0x04A6: + return new int[] {0x04A7}; + case 0x1FAE: + return new int[] {0x1F66, 0x03B9}; + case 0x1D796: + return new int[] {0x03B7}; + case 0x1D799: + return new int[] {0x03BA}; + default: + return new int[] {codePoint}; + } + } + + /** + * Mapping for case-folding used with no normalization. + * + * @param codePoint the character (Unicode code point) to be mapped. + * @return Case-folding used with no normalization for the given {@code codePoint}. + * @see RFC 3454, Appendix B.3 + */ + public static int[] mapWithoutNormalization(int codePoint) { + switch (codePoint) { + case 0x00C5: + return new int[] {0x00E5}; + case 0x00C6: + return new int[] {0x00E6}; + case 0x00C3: + return new int[] {0x00E3}; + case 0x00C4: + return new int[] {0x00E4}; + case 0x00C9: + return new int[] {0x00E9}; + case 0x00C7: + return new int[] {0x00E7}; + case 0x00C8: + return new int[] {0x00E8}; + case 0x00C1: + return new int[] {0x00E1}; + case 0x00C2: + return new int[] {0x00E2}; + case 0x00C0: + return new int[] {0x00E0}; + case 0x00D6: + return new int[] {0x00F6}; + case 0x00D4: + return new int[] {0x00F4}; + case 0x00D5: + return new int[] {0x00F5}; + case 0x00D8: + return new int[] {0x00F8}; + case 0x00D9: + return new int[] {0x00F9}; + case 0x00D2: + return new int[] {0x00F2}; + case 0x00D3: + return new int[] {0x00F3}; + case 0x00D0: + return new int[] {0x00F0}; + case 0x00D1: + return new int[] {0x00F1}; + case 0x00CE: + return new int[] {0x00EE}; + case 0x00CF: + return new int[] {0x00EF}; + case 0x00CC: + return new int[] {0x00EC}; + case 0x00CD: + return new int[] {0x00ED}; + case 0x00CA: + return new int[] {0x00EA}; + case 0x00CB: + return new int[] {0x00EB}; + case 0x00DF: + return new int[] {0x0073, 0x0073}; + case 0x00DD: + return new int[] {0x00FD}; + case 0x00DE: + return new int[] {0x00FE}; + case 0x00DB: + return new int[] {0x00FB}; + case 0x00DC: + return new int[] {0x00FC}; + case 0x00DA: + return new int[] {0x00FA}; + case 0x24B7: + return new int[] {0x24D1}; + case 0x24B6: + return new int[] {0x24D0}; + case 0x24C4: + return new int[] {0x24DE}; + case 0x24C3: + return new int[] {0x24DD}; + case 0x24C2: + return new int[] {0x24DC}; + case 0x24C1: + return new int[] {0x24DB}; + case 0x24C8: + return new int[] {0x24E2}; + case 0x24C7: + return new int[] {0x24E1}; + case 0x24C6: + return new int[] {0x24E0}; + case 0x24C5: + return new int[] {0x24DF}; + case 0x24C0: + return new int[] {0x24DA}; + case 0x24BC: + return new int[] {0x24D6}; + case 0x24BB: + return new int[] {0x24D5}; + case 0x24BA: + return new int[] {0x24D4}; + case 0x24BF: + return new int[] {0x24D9}; + case 0x24BE: + return new int[] {0x24D8}; + case 0x24BD: + return new int[] {0x24D7}; + case 0x24B9: + return new int[] {0x24D3}; + case 0x24B8: + return new int[] {0x24D2}; + case 0x00B5: + return new int[] {0x03BC}; + case 0x24CD: + return new int[] {0x24E7}; + case 0x24CC: + return new int[] {0x24E6}; + case 0x24CB: + return new int[] {0x24E5}; + case 0x24CA: + return new int[] {0x24E4}; + case 0x24CF: + return new int[] {0x24E9}; + case 0x24CE: + return new int[] {0x24E8}; + case 0x24C9: + return new int[] {0x24E3}; + case 0x054A: + return new int[] {0x057A}; + case 0x054B: + return new int[] {0x057B}; + case 0x1E10: + return new int[] {0x1E11}; + case 0x054E: + return new int[] {0x057E}; + case 0x054F: + return new int[] {0x057F}; + case 0x1E14: + return new int[] {0x1E15}; + case 0x054C: + return new int[] {0x057C}; + case 0x054D: + return new int[] {0x057D}; + case 0x1E12: + return new int[] {0x1E13}; + case 0x0549: + return new int[] {0x0579}; + case 0x0547: + return new int[] {0x0577}; + case 0x0548: + return new int[] {0x0578}; + case 0x1E0E: + return new int[] {0x1E0F}; + case 0x0541: + return new int[] {0x0571}; + case 0x0542: + return new int[] {0x0572}; + case 0x0540: + return new int[] {0x0570}; + case 0x0545: + return new int[] {0x0575}; + case 0x0546: + return new int[] {0x0576}; + case 0x1E0C: + return new int[] {0x1E0D}; + case 0x0543: + return new int[] {0x0573}; + case 0x0544: + return new int[] {0x0574}; + case 0x1E0A: + return new int[] {0x1E0B}; + case 0x1E06: + return new int[] {0x1E07}; + case 0x053F: + return new int[] {0x056F}; + case 0x1E04: + return new int[] {0x1E05}; + case 0x1E08: + return new int[] {0x1E09}; + case 0x1E20: + return new int[] {0x1E21}; + case 0x1E24: + return new int[] {0x1E25}; + case 0x1E22: + return new int[] {0x1E23}; + case 0x1E1E: + return new int[] {0x1E1F}; + case 0x0552: + return new int[] {0x0582}; + case 0x0553: + return new int[] {0x0583}; + case 0x0550: + return new int[] {0x0580}; + case 0x0551: + return new int[] {0x0581}; + case 0x0556: + return new int[] {0x0586}; + case 0x1E1C: + return new int[] {0x1E1D}; + case 0x0554: + return new int[] {0x0584}; + case 0x1E1A: + return new int[] {0x1E1B}; + case 0x0555: + return new int[] {0x0585}; + case 0x1E18: + return new int[] {0x1E19}; + case 0x1E16: + return new int[] {0x1E17}; + case 0x1E32: + return new int[] {0x1E33}; + case 0x1E30: + return new int[] {0x1E31}; + case 0x1E36: + return new int[] {0x1E37}; + case 0x1E34: + return new int[] {0x1E35}; + case 0x1E2A: + return new int[] {0x1E2B}; + case 0x1E2E: + return new int[] {0x1E2F}; + case 0x1E2C: + return new int[] {0x1E2D}; + case 0x1E28: + return new int[] {0x1E29}; + case 0x1E26: + return new int[] {0x1E27}; + case 0x1E42: + return new int[] {0x1E43}; + case 0x1E40: + return new int[] {0x1E41}; + case 0x1E46: + return new int[] {0x1E47}; + case 0x1E44: + return new int[] {0x1E45}; + case 0x1E3A: + return new int[] {0x1E3B}; + case 0x1E3E: + return new int[] {0x1E3F}; + case 0x1E3C: + return new int[] {0x1E3D}; + case 0x1E38: + return new int[] {0x1E39}; + case 0x050A: + return new int[] {0x050B}; + case 0x0506: + return new int[] {0x0507}; + case 0x0504: + return new int[] {0x0505}; + case 0x0508: + return new int[] {0x0509}; + case 0x0502: + return new int[] {0x0503}; + case 0x0500: + return new int[] {0x0501}; + case 0x050E: + return new int[] {0x050F}; + case 0x050C: + return new int[] {0x050D}; + case 0xFF30: + return new int[] {0xFF50}; + case 0xFF31: + return new int[] {0xFF51}; + case 0xFF32: + return new int[] {0xFF52}; + case 0xFF37: + return new int[] {0xFF57}; + case 0xFF38: + return new int[] {0xFF58}; + case 0xFF39: + return new int[] {0xFF59}; + case 0xFF33: + return new int[] {0xFF53}; + case 0xFF34: + return new int[] {0xFF54}; + case 0xFF35: + return new int[] {0xFF55}; + case 0xFF36: + return new int[] {0xFF56}; + case 0xFF3A: + return new int[] {0xFF5A}; + case 0x053A: + return new int[] {0x056A}; + case 0xFF21: + return new int[] {0xFF41}; + case 0x053D: + return new int[] {0x056D}; + case 0x1E02: + return new int[] {0x1E03}; + case 0x053E: + return new int[] {0x056E}; + case 0x053B: + return new int[] {0x056B}; + case 0x1E00: + return new int[] {0x1E01}; + case 0x053C: + return new int[] {0x056C}; + case 0x0538: + return new int[] {0x0568}; + case 0xFF26: + return new int[] {0xFF46}; + case 0x0539: + return new int[] {0x0569}; + case 0xFF27: + return new int[] {0xFF47}; + case 0x0536: + return new int[] {0x0566}; + case 0xFF28: + return new int[] {0xFF48}; + case 0x0537: + return new int[] {0x0567}; + case 0xFF29: + return new int[] {0xFF49}; + case 0xFF22: + return new int[] {0xFF42}; + case 0xFF23: + return new int[] {0xFF43}; + case 0xFF24: + return new int[] {0xFF44}; + case 0xFF25: + return new int[] {0xFF45}; + case 0x0531: + return new int[] {0x0561}; + case 0xFF2A: + return new int[] {0xFF4A}; + case 0x0534: + return new int[] {0x0564}; + case 0x0535: + return new int[] {0x0565}; + case 0x0532: + return new int[] {0x0562}; + case 0x0533: + return new int[] {0x0563}; + case 0xFF2F: + return new int[] {0xFF4F}; + case 0xFF2B: + return new int[] {0xFF4B}; + case 0xFF2C: + return new int[] {0xFF4C}; + case 0xFF2D: + return new int[] {0xFF4D}; + case 0xFF2E: + return new int[] {0xFF4E}; + case 0x014E: + return new int[] {0x014F}; + case 0x1E97: + return new int[] {0x0074, 0x0308}; + case 0x1E98: + return new int[] {0x0077, 0x030A}; + case 0x014C: + return new int[] {0x014D}; + case 0x038E: + return new int[] {0x03CD}; + case 0x038F: + return new int[] {0x03CE}; + case 0x1E96: + return new int[] {0x0068, 0x0331}; + case 0x1E99: + return new int[] {0x0079, 0x030A}; + case 0x1E90: + return new int[] {0x1E91}; + case 0x014A: + return new int[] {0x014B}; + case 0x038C: + return new int[] {0x03CC}; + case 0x1E94: + return new int[] {0x1E95}; + case 0x038A: + return new int[] {0x03AF}; + case 0x1E92: + return new int[] {0x1E93}; + case 0x0145: + return new int[] {0x0146}; + case 0x0388: + return new int[] {0x03AD}; + case 0x0143: + return new int[] {0x0144}; + case 0x0386: + return new int[] {0x03AC}; + case 0x1E8E: + return new int[] {0x1E8F}; + case 0x0149: + return new int[] {0x02BC, 0x006E}; + case 0x0147: + return new int[] {0x0148}; + case 0x0389: + return new int[] {0x03AE}; + case 0x0141: + return new int[] {0x0142}; + case 0x1E8C: + return new int[] {0x1E8D}; + case 0x1E8A: + return new int[] {0x1E8B}; + case 0x039F: + return new int[] {0x03BF}; + case 0x015E: + return new int[] {0x015F}; + case 0x039A: + return new int[] {0x03BA}; + case 0x039D: + return new int[] {0x03BD}; + case 0x015C: + return new int[] {0x015D}; + case 0x039E: + return new int[] {0x03BE}; + case 0x039B: + return new int[] {0x03BB}; + case 0x015A: + return new int[] {0x015B}; + case 0x039C: + return new int[] {0x03BC}; + case 0x0156: + return new int[] {0x0157}; + case 0x0398: + return new int[] {0x03B8}; + case 0x0399: + return new int[] {0x03B9}; + case 0x0154: + return new int[] {0x0155}; + case 0x0396: + return new int[] {0x03B6}; + case 0x0397: + return new int[] {0x03B7}; + case 0x0158: + return new int[] {0x0159}; + case 0x0390: + return new int[] {0x03B9, 0x0308, 0x0301}; + case 0x0391: + return new int[] {0x03B1}; + case 0x0152: + return new int[] {0x0153}; + case 0x0394: + return new int[] {0x03B4}; + case 0x0395: + return new int[] {0x03B5}; + case 0x0150: + return new int[] {0x0151}; + case 0x0392: + return new int[] {0x03B2}; + case 0x1E9A: + return new int[] {0x0061, 0x02BE}; + case 0x0393: + return new int[] {0x03B3}; + case 0x1E9B: + return new int[] {0x1E61}; + case 0x016E: + return new int[] {0x016F}; + case 0x016C: + return new int[] {0x016D}; + case 0x016A: + return new int[] {0x016B}; + case 0x0168: + return new int[] {0x0169}; + case 0x0166: + return new int[] {0x0167}; + case 0x0160: + return new int[] {0x0161}; + case 0x0164: + return new int[] {0x0165}; + case 0x0162: + return new int[] {0x0163}; + case 0x017F: + return new int[] {0x0073}; + case 0x017D: + return new int[] {0x017E}; + case 0x017B: + return new int[] {0x017C}; + case 0x0178: + return new int[] {0x00FF}; + case 0x0179: + return new int[] {0x017A}; + case 0x0176: + return new int[] {0x0177}; + case 0x0170: + return new int[] {0x0171}; + case 0x0174: + return new int[] {0x0175}; + case 0x0172: + return new int[] {0x0173}; + case 0x010A: + return new int[] {0x010B}; + case 0x1E54: + return new int[] {0x1E55}; + case 0xFB13: + return new int[] {0x0574, 0x0576}; + case 0x1E52: + return new int[] {0x1E53}; + case 0xFB14: + return new int[] {0x0574, 0x0565}; + case 0x010E: + return new int[] {0x010F}; + case 0x1E58: + return new int[] {0x1E59}; + case 0x010C: + return new int[] {0x010D}; + case 0x1E56: + return new int[] {0x1E57}; + case 0x0108: + return new int[] {0x0109}; + case 0xFB15: + return new int[] {0x0574, 0x056B}; + case 0x1E50: + return new int[] {0x1E51}; + case 0xFB16: + return new int[] {0x057E, 0x0576}; + case 0xFB17: + return new int[] {0x0574, 0x056D}; + case 0x0102: + return new int[] {0x0103}; + case 0x1E4C: + return new int[] {0x1E4D}; + case 0x0100: + return new int[] {0x0101}; + case 0x1E4A: + return new int[] {0x1E4B}; + case 0x0106: + return new int[] {0x0107}; + case 0x0345: + return new int[] {0x03B9}; + case 0x0587: + return new int[] {0x0565, 0x0582}; + case 0x0104: + return new int[] {0x0105}; + case 0x1E4E: + return new int[] {0x1E4F}; + case 0x1E48: + return new int[] {0x1E49}; + case 0x1E64: + return new int[] {0x1E65}; + case 0xFB00: + return new int[] {0x0066, 0x0066}; + case 0x011C: + return new int[] {0x011D}; + case 0xFB01: + return new int[] {0x0066, 0x0069}; + case 0x1E62: + return new int[] {0x1E63}; + case 0xFB02: + return new int[] {0x0066, 0x006C}; + case 0x011A: + return new int[] {0x011B}; + case 0xFB03: + return new int[] {0x0066, 0x0066, 0x0069}; + case 0x1E68: + return new int[] {0x1E69}; + case 0x1E66: + return new int[] {0x1E67}; + case 0x011E: + return new int[] {0x011F}; + case 0x0118: + return new int[] {0x0119}; + case 0x1E60: + return new int[] {0x1E61}; + case 0xFB04: + return new int[] {0x0066, 0x0066, 0x006C}; + case 0xFB05: + return new int[] {0x0073, 0x0074}; + case 0xFB06: + return new int[] {0x0073, 0x0074}; + case 0x0112: + return new int[] {0x0113}; + case 0x1E5C: + return new int[] {0x1E5D}; + case 0x0110: + return new int[] {0x0111}; + case 0x1E5A: + return new int[] {0x1E5B}; + case 0x0116: + return new int[] {0x0117}; + case 0x0114: + return new int[] {0x0115}; + case 0x1E5E: + return new int[] {0x1E5F}; + case 0x012C: + return new int[] {0x012D}; + case 0x1E76: + return new int[] {0x1E77}; + case 0x012A: + return new int[] {0x012B}; + case 0x1E74: + return new int[] {0x1E75}; + case 0x012E: + return new int[] {0x012F}; + case 0x1E78: + return new int[] {0x1E79}; + case 0x1E72: + return new int[] {0x1E73}; + case 0x1E70: + return new int[] {0x1E71}; + case 0x0124: + return new int[] {0x0125}; + case 0x1E6E: + return new int[] {0x1E6F}; + case 0x0122: + return new int[] {0x0123}; + case 0x1E6C: + return new int[] {0x1E6D}; + case 0x0128: + return new int[] {0x0129}; + case 0x0126: + return new int[] {0x0127}; + case 0x0120: + return new int[] {0x0121}; + case 0x1E6A: + return new int[] {0x1E6B}; + case 0x013D: + return new int[] {0x013E}; + case 0x1E86: + return new int[] {0x1E87}; + case 0x013B: + return new int[] {0x013C}; + case 0x1E84: + return new int[] {0x1E85}; + case 0x013F: + return new int[] {0x0140}; + case 0x1E88: + return new int[] {0x1E89}; + case 0x1E82: + return new int[] {0x1E83}; + case 0x1E80: + return new int[] {0x1E81}; + case 0x0134: + return new int[] {0x0135}; + case 0x1E7E: + return new int[] {0x1E7F}; + case 0x0132: + return new int[] {0x0133}; + case 0x1E7C: + return new int[] {0x1E7D}; + case 0x0139: + return new int[] {0x013A}; + case 0x0136: + return new int[] {0x0137}; + case 0x0130: + return new int[] {0x0069, 0x0307}; + case 0x1E7A: + return new int[] {0x1E7B}; + case 0x03A0: + return new int[] {0x03C0}; + case 0x03A1: + return new int[] {0x03C1}; + case 0x03A4: + return new int[] {0x03C4}; + case 0x1EAC: + return new int[] {0x1EAD}; + case 0x03A5: + return new int[] {0x03C5}; + case 0x1EAA: + return new int[] {0x1EAB}; + case 0x03A3: + return new int[] {0x03C3}; + case 0x216B: + return new int[] {0x217B}; + case 0x1EA8: + return new int[] {0x1EA9}; + case 0x216A: + return new int[] {0x217A}; + case 0x10425: + return new int[] {0x1044D}; + case 0x1EA6: + return new int[] {0x1EA7}; + case 0x216F: + return new int[] {0x217F}; + case 0x216E: + return new int[] {0x217E}; + case 0x216D: + return new int[] {0x217D}; + case 0x216C: + return new int[] {0x217C}; + case 0x1EA0: + return new int[] {0x1EA1}; + case 0x2169: + return new int[] {0x2179}; + case 0x2168: + return new int[] {0x2178}; + case 0x10420: + return new int[] {0x10448}; + case 0x2167: + return new int[] {0x2177}; + case 0x10422: + return new int[] {0x1044A}; + case 0x1EA4: + return new int[] {0x1EA5}; + case 0x10421: + return new int[] {0x10449}; + case 0x10424: + return new int[] {0x1044C}; + case 0x1EA2: + return new int[] {0x1EA3}; + case 0x10423: + return new int[] {0x1044B}; + case 0x2162: + return new int[] {0x2172}; + case 0x1041E: + return new int[] {0x10446}; + case 0x2161: + return new int[] {0x2171}; + case 0x1041D: + return new int[] {0x10445}; + case 0x2160: + return new int[] {0x2170}; + case 0x1041F: + return new int[] {0x10447}; + case 0x2166: + return new int[] {0x2176}; + case 0x2165: + return new int[] {0x2175}; + case 0x2164: + return new int[] {0x2174}; + case 0x2163: + return new int[] {0x2173}; + case 0x1EBA: + return new int[] {0x1EBB}; + case 0x03B0: + return new int[] {0x03C5, 0x0308, 0x0301}; + case 0x1041A: + return new int[] {0x10442}; + case 0x1EBE: + return new int[] {0x1EBF}; + case 0x1041C: + return new int[] {0x10444}; + case 0x1EBC: + return new int[] {0x1EBD}; + case 0x1041B: + return new int[] {0x10443}; + case 0x1EB8: + return new int[] {0x1EB9}; + case 0x10415: + return new int[] {0x1043D}; + case 0x10414: + return new int[] {0x1043C}; + case 0x1EB6: + return new int[] {0x1EB7}; + case 0x10417: + return new int[] {0x1043F}; + case 0x10416: + return new int[] {0x1043E}; + case 0x10419: + return new int[] {0x10441}; + case 0x10418: + return new int[] {0x10440}; + case 0x1EB0: + return new int[] {0x1EB1}; + case 0x03AA: + return new int[] {0x03CA}; + case 0x1EB4: + return new int[] {0x1EB5}; + case 0x10411: + return new int[] {0x10439}; + case 0x10410: + return new int[] {0x10438}; + case 0x03AB: + return new int[] {0x03CB}; + case 0x1EB2: + return new int[] {0x1EB3}; + case 0x10413: + return new int[] {0x1043B}; + case 0x10412: + return new int[] {0x1043A}; + case 0x03A8: + return new int[] {0x03C8}; + case 0x1040D: + return new int[] {0x10435}; + case 0x03A9: + return new int[] {0x03C9}; + case 0x1040C: + return new int[] {0x10434}; + case 0x03A6: + return new int[] {0x03C6}; + case 0x1EAE: + return new int[] {0x1EAF}; + case 0x1040F: + return new int[] {0x10437}; + case 0x03A7: + return new int[] {0x03C7}; + case 0x1040E: + return new int[] {0x10436}; + case 0x03C2: + return new int[] {0x03C3}; + case 0x1ECA: + return new int[] {0x1ECB}; + case 0x1ECE: + return new int[] {0x1ECF}; + case 0x1ECC: + return new int[] {0x1ECD}; + case 0x1EC8: + return new int[] {0x1EC9}; + case 0x1EC2: + return new int[] {0x1EC3}; + case 0x1EC0: + return new int[] {0x1EC1}; + case 0x1EC6: + return new int[] {0x1EC7}; + case 0x1EC4: + return new int[] {0x1EC5}; + case 0x1EDC: + return new int[] {0x1EDD}; + case 0x03D1: + return new int[] {0x03B8}; + case 0x1EDA: + return new int[] {0x1EDB}; + case 0x03D8: + return new int[] {0x03D9}; + case 0x03D5: + return new int[] {0x03C6}; + case 0x03D6: + return new int[] {0x03C0}; + case 0x1EDE: + return new int[] {0x1EDF}; + case 0x1ED8: + return new int[] {0x1ED9}; + case 0x03D0: + return new int[] {0x03B2}; + case 0x1ED2: + return new int[] {0x1ED3}; + case 0x1ED0: + return new int[] {0x1ED1}; + case 0x1ED6: + return new int[] {0x1ED7}; + case 0x1ED4: + return new int[] {0x1ED5}; + case 0x018A: + return new int[] {0x0257}; + case 0x018B: + return new int[] {0x018C}; + case 0x018E: + return new int[] {0x01DD}; + case 0x212B: + return new int[] {0x00E5}; + case 0x018F: + return new int[] {0x0259}; + case 0x212A: + return new int[] {0x006B}; + case 0x0189: + return new int[] {0x0256}; + case 0x2126: + return new int[] {0x03C9}; + case 0x0187: + return new int[] {0x0188}; + case 0x0181: + return new int[] {0x0253}; + case 0x0182: + return new int[] {0x0183}; + case 0x0186: + return new int[] {0x0254}; + case 0x0184: + return new int[] {0x0185}; + case 0x019C: + return new int[] {0x026F}; + case 0x019F: + return new int[] {0x0275}; + case 0x019D: + return new int[] {0x0272}; + case 0x0198: + return new int[] {0x0199}; + case 0x0193: + return new int[] {0x0260}; + case 0x0190: + return new int[] {0x025B}; + case 0x0191: + return new int[] {0x0192}; + case 0x0196: + return new int[] {0x0269}; + case 0x0197: + return new int[] {0x0268}; + case 0x0194: + return new int[] {0x0263}; + case 0x1040B: + return new int[] {0x10433}; + case 0x1040A: + return new int[] {0x10432}; + case 0x10404: + return new int[] {0x1042C}; + case 0x10403: + return new int[] {0x1042B}; + case 0x10406: + return new int[] {0x1042E}; + case 0x10405: + return new int[] {0x1042D}; + case 0x10408: + return new int[] {0x10430}; + case 0x10407: + return new int[] {0x1042F}; + case 0x10409: + return new int[] {0x10431}; + case 0x10400: + return new int[] {0x10428}; + case 0x10402: + return new int[] {0x1042A}; + case 0x10401: + return new int[] {0x10429}; + case 0x01E6: + return new int[] {0x01E7}; + case 0x01E4: + return new int[] {0x01E5}; + case 0x01E8: + return new int[] {0x01E9}; + case 0x01E2: + return new int[] {0x01E3}; + case 0x01E0: + return new int[] {0x01E1}; + case 0x01DE: + return new int[] {0x01DF}; + case 0x01DB: + return new int[] {0x01DC}; + case 0x01F7: + return new int[] {0x01BF}; + case 0x01F8: + return new int[] {0x01F9}; + case 0x01F6: + return new int[] {0x0195}; + case 0x01F0: + return new int[] {0x006A, 0x030C}; + case 0x01F4: + return new int[] {0x01F5}; + case 0x01F1: + return new int[] {0x01F3}; + case 0x01F2: + return new int[] {0x01F3}; + case 0x01EE: + return new int[] {0x01EF}; + case 0x01EC: + return new int[] {0x01ED}; + case 0x01EA: + return new int[] {0x01EB}; + case 0x01FE: + return new int[] {0x01FF}; + case 0x01FC: + return new int[] {0x01FD}; + case 0x01FA: + return new int[] {0x01FB}; + case 0x01A2: + return new int[] {0x01A3}; + case 0x03E4: + return new int[] {0x03E5}; + case 0x1EEC: + return new int[] {0x1EED}; + case 0x01A0: + return new int[] {0x01A1}; + case 0x03E2: + return new int[] {0x03E3}; + case 0x1EEA: + return new int[] {0x1EEB}; + case 0x01A6: + return new int[] {0x0280}; + case 0x03E8: + return new int[] {0x03E9}; + case 0x01A7: + return new int[] {0x01A8}; + case 0x01A4: + return new int[] {0x01A5}; + case 0x03E6: + return new int[] {0x03E7}; + case 0x1EEE: + return new int[] {0x1EEF}; + case 0x03E0: + return new int[] {0x03E1}; + case 0x03DC: + return new int[] {0x03DD}; + case 0x1EE4: + return new int[] {0x1EE5}; + case 0x03DA: + return new int[] {0x03DB}; + case 0x1EE2: + return new int[] {0x1EE3}; + case 0x1EE8: + return new int[] {0x1EE9}; + case 0x03DE: + return new int[] {0x03DF}; + case 0x1EE6: + return new int[] {0x1EE7}; + case 0x1EE0: + return new int[] {0x1EE1}; + case 0x01B3: + return new int[] {0x01B4}; + case 0x03F5: + return new int[] {0x03B5}; + case 0x01B1: + return new int[] {0x028A}; + case 0x01B2: + return new int[] {0x028B}; + case 0x03F4: + return new int[] {0x03B8}; + case 0x01B7: + return new int[] {0x0292}; + case 0x01B8: + return new int[] {0x01B9}; + case 0x01B5: + return new int[] {0x01B6}; + case 0x03F1: + return new int[] {0x03C1}; + case 0x03F2: + return new int[] {0x03C3}; + case 0x03F0: + return new int[] {0x03BA}; + case 0x1EF4: + return new int[] {0x1EF5}; + case 0x01AC: + return new int[] {0x01AD}; + case 0x03EE: + return new int[] {0x03EF}; + case 0x1EF2: + return new int[] {0x1EF3}; + case 0x03EC: + return new int[] {0x03ED}; + case 0x01AF: + return new int[] {0x01B0}; + case 0x1EF8: + return new int[] {0x1EF9}; + case 0x1EF6: + return new int[] {0x1EF7}; + case 0x01AE: + return new int[] {0x0288}; + case 0x01A9: + return new int[] {0x0283}; + case 0x1EF0: + return new int[] {0x1EF1}; + case 0x03EA: + return new int[] {0x03EB}; + case 0x01C4: + return new int[] {0x01C6}; + case 0x01C5: + return new int[] {0x01C6}; + case 0x01C8: + return new int[] {0x01C9}; + case 0x01C7: + return new int[] {0x01C9}; + case 0x01BC: + return new int[] {0x01BD}; + case 0x01D5: + return new int[] {0x01D6}; + case 0x01D3: + return new int[] {0x01D4}; + case 0x01D9: + return new int[] {0x01DA}; + case 0x01D7: + return new int[] {0x01D8}; + case 0x01D1: + return new int[] {0x01D2}; + case 0x01CD: + return new int[] {0x01CE}; + case 0x01CB: + return new int[] {0x01CC}; + case 0x01CF: + return new int[] {0x01D0}; + case 0x01CA: + return new int[] {0x01CC}; + case 0x042A: + return new int[] {0x044A}; + case 0x042D: + return new int[] {0x044D}; + case 0x042E: + return new int[] {0x044E}; + case 0x042B: + return new int[] {0x044B}; + case 0x042C: + return new int[] {0x044C}; + case 0x0428: + return new int[] {0x0448}; + case 0x0429: + return new int[] {0x0449}; + case 0x0426: + return new int[] {0x0446}; + case 0x1F2E: + return new int[] {0x1F26}; + case 0x0427: + return new int[] {0x0447}; + case 0x1F2F: + return new int[] {0x1F27}; + case 0x0420: + return new int[] {0x0440}; + case 0x0421: + return new int[] {0x0441}; + case 0x0424: + return new int[] {0x0444}; + case 0x1F2C: + return new int[] {0x1F24}; + case 0x0425: + return new int[] {0x0445}; + case 0x1F2D: + return new int[] {0x1F25}; + case 0x0422: + return new int[] {0x0442}; + case 0x1F2A: + return new int[] {0x1F22}; + case 0x0423: + return new int[] {0x0443}; + case 0x1F2B: + return new int[] {0x1F23}; + case 0x1F28: + return new int[] {0x1F20}; + case 0x041E: + return new int[] {0x043E}; + case 0x041F: + return new int[] {0x043F}; + case 0x1F29: + return new int[] {0x1F21}; + case 0x1F3F: + return new int[] {0x1F37}; + case 0x1F3A: + return new int[] {0x1F32}; + case 0x1F3D: + return new int[] {0x1F35}; + case 0x1F3E: + return new int[] {0x1F36}; + case 0x1F3B: + return new int[] {0x1F33}; + case 0x1F3C: + return new int[] {0x1F34}; + case 0x1F38: + return new int[] {0x1F30}; + case 0x1F39: + return new int[] {0x1F31}; + case 0x042F: + return new int[] {0x044F}; + case 0x1F52: + return new int[] {0x03C5, 0x0313, 0x0300}; + case 0x020A: + return new int[] {0x020B}; + case 0x1F50: + return new int[] {0x03C5, 0x0313}; + case 0x1F56: + return new int[] {0x03C5, 0x0313, 0x0342}; + case 0x020E: + return new int[] {0x020F}; + case 0x1F54: + return new int[] {0x03C5, 0x0313, 0x0301}; + case 0x020C: + return new int[] {0x020D}; + case 0x0208: + return new int[] {0x0209}; + case 0x0206: + return new int[] {0x0207}; + case 0x0200: + return new int[] {0x0201}; + case 0x1F4A: + return new int[] {0x1F42}; + case 0x1F4B: + return new int[] {0x1F43}; + case 0x0204: + return new int[] {0x0205}; + case 0x0202: + return new int[] {0x0203}; + case 0x1F4C: + return new int[] {0x1F44}; + case 0x1F4D: + return new int[] {0x1F45}; + case 0x1F49: + return new int[] {0x1F41}; + case 0x1F48: + return new int[] {0x1F40}; + case 0x021A: + return new int[] {0x021B}; + case 0x021E: + return new int[] {0x021F}; + case 0x1F68: + return new int[] {0x1F60}; + case 0x021C: + return new int[] {0x021D}; + case 0x0218: + return new int[] {0x0219}; + case 0x1F5B: + return new int[] {0x1F53}; + case 0x0212: + return new int[] {0x0213}; + case 0x0210: + return new int[] {0x0211}; + case 0x1F5F: + return new int[] {0x1F57}; + case 0x0216: + return new int[] {0x0217}; + case 0x1F5D: + return new int[] {0x1F55}; + case 0x0214: + return new int[] {0x0215}; + case 0x1F59: + return new int[] {0x1F51}; + case 0x040B: + return new int[] {0x045B}; + case 0x040C: + return new int[] {0x045C}; + case 0x040A: + return new int[] {0x045A}; + case 0x0406: + return new int[] {0x0456}; + case 0x1F0E: + return new int[] {0x1F06}; + case 0x0407: + return new int[] {0x0457}; + case 0x1F0F: + return new int[] {0x1F07}; + case 0x0404: + return new int[] {0x0454}; + case 0x1F0C: + return new int[] {0x1F04}; + case 0x0405: + return new int[] {0x0455}; + case 0x1F0D: + return new int[] {0x1F05}; + case 0x0408: + return new int[] {0x0458}; + case 0x0409: + return new int[] {0x0459}; + case 0x0402: + return new int[] {0x0452}; + case 0x1F0A: + return new int[] {0x1F02}; + case 0x0403: + return new int[] {0x0453}; + case 0x1F0B: + return new int[] {0x1F03}; + case 0x0400: + return new int[] {0x0450}; + case 0x0401: + return new int[] {0x0451}; + case 0x1F09: + return new int[] {0x1F01}; + case 0x1F08: + return new int[] {0x1F00}; + case 0x041C: + return new int[] {0x043C}; + case 0x041D: + return new int[] {0x043D}; + case 0x041A: + return new int[] {0x043A}; + case 0x041B: + return new int[] {0x043B}; + case 0x0417: + return new int[] {0x0437}; + case 0x0418: + return new int[] {0x0438}; + case 0x0415: + return new int[] {0x0435}; + case 0x1F1D: + return new int[] {0x1F15}; + case 0x0416: + return new int[] {0x0436}; + case 0x0419: + return new int[] {0x0439}; + case 0x0410: + return new int[] {0x0430}; + case 0x0413: + return new int[] {0x0433}; + case 0x1F1B: + return new int[] {0x1F13}; + case 0x0414: + return new int[] {0x0434}; + case 0x1F1C: + return new int[] {0x1F14}; + case 0x0411: + return new int[] {0x0431}; + case 0x0412: + return new int[] {0x0432}; + case 0x1F1A: + return new int[] {0x1F12}; + case 0x040F: + return new int[] {0x045F}; + case 0x040D: + return new int[] {0x045D}; + case 0x040E: + return new int[] {0x045E}; + case 0x1F18: + return new int[] {0x1F10}; + case 0x1F19: + return new int[] {0x1F11}; + case 0x004F: + return new int[] {0x006F}; + case 0x004D: + return new int[] {0x006D}; + case 0x004E: + return new int[] {0x006E}; + case 0x004B: + return new int[] {0x006B}; + case 0x004C: + return new int[] {0x006C}; + case 0x004A: + return new int[] {0x006A}; + case 0x0046: + return new int[] {0x0066}; + case 0x0047: + return new int[] {0x0067}; + case 0x0044: + return new int[] {0x0064}; + case 0x0045: + return new int[] {0x0065}; + case 0x0048: + return new int[] {0x0068}; + case 0x0049: + return new int[] {0x0069}; + case 0x0042: + return new int[] {0x0062}; + case 0x0043: + return new int[] {0x0063}; + case 0x0041: + return new int[] {0x0061}; + case 0x005A: + return new int[] {0x007A}; + case 0x0057: + return new int[] {0x0077}; + case 0x0058: + return new int[] {0x0078}; + case 0x0055: + return new int[] {0x0075}; + case 0x0056: + return new int[] {0x0076}; + case 0x0059: + return new int[] {0x0079}; + case 0x0050: + return new int[] {0x0070}; + case 0x0053: + return new int[] {0x0073}; + case 0x0054: + return new int[] {0x0074}; + case 0x0051: + return new int[] {0x0071}; + case 0x0052: + return new int[] {0x0072}; + case 0x022C: + return new int[] {0x022D}; + case 0x046E: + return new int[] {0x046F}; + case 0x022A: + return new int[] {0x022B}; + case 0x046C: + return new int[] {0x046D}; + case 0x022E: + return new int[] {0x022F}; + case 0x0228: + return new int[] {0x0229}; + case 0x046A: + return new int[] {0x046B}; + case 0x0222: + return new int[] {0x0223}; + case 0x0464: + return new int[] {0x0465}; + case 0x1F6C: + return new int[] {0x1F64}; + case 0x1F6D: + return new int[] {0x1F65}; + case 0x0220: + return new int[] {0x019E}; + case 0x0462: + return new int[] {0x0463}; + case 0x1F6A: + return new int[] {0x1F62}; + case 0x1F6B: + return new int[] {0x1F63}; + case 0x0226: + return new int[] {0x0227}; + case 0x0468: + return new int[] {0x0469}; + case 0x0224: + return new int[] {0x0225}; + case 0x0466: + return new int[] {0x0467}; + case 0x1F6E: + return new int[] {0x1F66}; + case 0x1F6F: + return new int[] {0x1F67}; + case 0x1F69: + return new int[] {0x1F61}; + case 0x0460: + return new int[] {0x0461}; + case 0x047E: + return new int[] {0x047F}; + case 0x1F85: + return new int[] {0x1F05, 0x03B9}; + case 0x1F86: + return new int[] {0x1F06, 0x03B9}; + case 0x047C: + return new int[] {0x047D}; + case 0x1F83: + return new int[] {0x1F03, 0x03B9}; + case 0x1F84: + return new int[] {0x1F04, 0x03B9}; + case 0x1F89: + return new int[] {0x1F01, 0x03B9}; + case 0x1F87: + return new int[] {0x1F07, 0x03B9}; + case 0x1F88: + return new int[] {0x1F00, 0x03B9}; + case 0x047A: + return new int[] {0x047B}; + case 0x1F81: + return new int[] {0x1F01, 0x03B9}; + case 0x1F82: + return new int[] {0x1F02, 0x03B9}; + case 0x1F80: + return new int[] {0x1F00, 0x03B9}; + case 0x0476: + return new int[] {0x0477}; + case 0x0232: + return new int[] {0x0233}; + case 0x0474: + return new int[] {0x0475}; + case 0x0478: + return new int[] {0x0479}; + case 0x0230: + return new int[] {0x0231}; + case 0x0472: + return new int[] {0x0473}; + case 0x0470: + return new int[] {0x0471}; + case 0x1F96: + return new int[] {0x1F26, 0x03B9}; + case 0x1F97: + return new int[] {0x1F27, 0x03B9}; + case 0x1F94: + return new int[] {0x1F24, 0x03B9}; + case 0x048E: + return new int[] {0x048F}; + case 0x1F95: + return new int[] {0x1F25, 0x03B9}; + case 0x1F98: + return new int[] {0x1F20, 0x03B9}; + case 0x1F99: + return new int[] {0x1F21, 0x03B9}; + case 0x1F92: + return new int[] {0x1F22, 0x03B9}; + case 0x048C: + return new int[] {0x048D}; + case 0x1F93: + return new int[] {0x1F23, 0x03B9}; + case 0x1F90: + return new int[] {0x1F20, 0x03B9}; + case 0x048A: + return new int[] {0x048B}; + case 0x1F91: + return new int[] {0x1F21, 0x03B9}; + case 0x1F8E: + return new int[] {0x1F06, 0x03B9}; + case 0x1F8F: + return new int[] {0x1F07, 0x03B9}; + case 0x1F8C: + return new int[] {0x1F04, 0x03B9}; + case 0x1F8D: + return new int[] {0x1F05, 0x03B9}; + case 0x1F8A: + return new int[] {0x1F02, 0x03B9}; + case 0x1F8B: + return new int[] {0x1F03, 0x03B9}; + case 0x0480: + return new int[] {0x0481}; + case 0x049E: + return new int[] {0x049F}; + case 0x049C: + return new int[] {0x049D}; + case 0x049A: + return new int[] {0x049B}; + case 0x1F9F: + return new int[] {0x1F27, 0x03B9}; + case 0x0498: + return new int[] {0x0499}; + case 0x1F9D: + return new int[] {0x1F25, 0x03B9}; + case 0x0496: + return new int[] {0x0497}; + case 0x1F9E: + return new int[] {0x1F26, 0x03B9}; + case 0x0490: + return new int[] {0x0491}; + case 0x1F9B: + return new int[] {0x1F23, 0x03B9}; + case 0x0494: + return new int[] {0x0495}; + case 0x1F9C: + return new int[] {0x1F24, 0x03B9}; + case 0x0492: + return new int[] {0x0493}; + case 0x1F9A: + return new int[] {0x1F22, 0x03B9}; + case 0x04C1: + return new int[] {0x04C2}; + case 0x1FCA: + return new int[] {0x1F74}; + case 0x04C5: + return new int[] {0x04C6}; + case 0x04C3: + return new int[] {0x04C4}; + case 0x1FCB: + return new int[] {0x1F75}; + case 0x1FCC: + return new int[] {0x03B7, 0x03B9}; + case 0x1FC8: + return new int[] {0x1F72}; + case 0x1FC9: + return new int[] {0x1F73}; + case 0x1FC6: + return new int[] {0x03B7, 0x0342}; + case 0x1FC7: + return new int[] {0x03B7, 0x0342, 0x03B9}; + case 0x04BA: + return new int[] {0x04BB}; + case 0x1FC4: + return new int[] {0x03AE, 0x03B9}; + case 0x04BE: + return new int[] {0x04BF}; + case 0x1FC2: + return new int[] {0x1F74, 0x03B9}; + case 0x04BC: + return new int[] {0x04BD}; + case 0x1FC3: + return new int[] {0x03B7, 0x03B9}; + case 0x04B8: + return new int[] {0x04B9}; + case 0x04B6: + return new int[] {0x04B7}; + case 0x1FBE: + return new int[] {0x03B9}; + case 0x04D2: + return new int[] {0x04D3}; + case 0x1FDA: + return new int[] {0x1F76}; + case 0x1FDB: + return new int[] {0x1F77}; + case 0x04D0: + return new int[] {0x04D1}; + case 0x04D6: + return new int[] {0x04D7}; + case 0x04D4: + return new int[] {0x04D5}; + case 0x1FD9: + return new int[] {0x1FD1}; + case 0x1FD7: + return new int[] {0x03B9, 0x0308, 0x0342}; + case 0x1FD8: + return new int[] {0x1FD0}; + case 0x04CB: + return new int[] {0x04CC}; + case 0x1FD2: + return new int[] {0x03B9, 0x0308, 0x0300}; + case 0x1FD6: + return new int[] {0x03B9, 0x0342}; + case 0x1FD3: + return new int[] {0x03B9, 0x0308, 0x0301}; + case 0x04CD: + return new int[] {0x04CE}; + case 0x04C9: + return new int[] {0x04CA}; + case 0x04C7: + return new int[] {0x04C8}; + case 0x1FEB: + return new int[] {0x1F7B}; + case 0x04E4: + return new int[] {0x04E5}; + case 0x1FEC: + return new int[] {0x1FE5}; + case 0x04E2: + return new int[] {0x04E3}; + case 0x1FEA: + return new int[] {0x1F7A}; + case 0x04E8: + return new int[] {0x04E9}; + case 0x04E6: + return new int[] {0x04E7}; + case 0x1FE8: + return new int[] {0x1FE0}; + case 0x1FE9: + return new int[] {0x1FE1}; + case 0x04E0: + return new int[] {0x04E1}; + case 0x1FE2: + return new int[] {0x03C5, 0x0308, 0x0300}; + case 0x04DC: + return new int[] {0x04DD}; + case 0x1FE3: + return new int[] {0x03C5, 0x0308, 0x0301}; + case 0x04DA: + return new int[] {0x04DB}; + case 0x1FE6: + return new int[] {0x03C5, 0x0342}; + case 0x1FE7: + return new int[] {0x03C5, 0x0308, 0x0342}; + case 0x1FE4: + return new int[] {0x03C1, 0x0313}; + case 0x04DE: + return new int[] {0x04DF}; + case 0x04D8: + return new int[] {0x04D9}; + case 0x04F4: + return new int[] {0x04F5}; + case 0x1FFC: + return new int[] {0x03C9, 0x03B9}; + case 0x04F2: + return new int[] {0x04F3}; + case 0x1FFA: + return new int[] {0x1F7C}; + case 0x1FFB: + return new int[] {0x1F7D}; + case 0x04F8: + return new int[] {0x04F9}; + case 0x1FF9: + return new int[] {0x1F79}; + case 0x04F0: + return new int[] {0x04F1}; + case 0x04EC: + return new int[] {0x04ED}; + case 0x1FF3: + return new int[] {0x03C9, 0x03B9}; + case 0x1FF4: + return new int[] {0x03CE, 0x03B9}; + case 0x04EA: + return new int[] {0x04EB}; + case 0x1FF2: + return new int[] {0x1F7C, 0x03B9}; + case 0x1FF7: + return new int[] {0x03C9, 0x0342, 0x03B9}; + case 0x1FF8: + return new int[] {0x1F78}; + case 0x04EE: + return new int[] {0x04EF}; + case 0x1FF6: + return new int[] {0x03C9, 0x0342}; + case 0x04A0: + return new int[] {0x04A1}; + case 0x1FAB: + return new int[] {0x1F63, 0x03B9}; + case 0x04A4: + return new int[] {0x04A5}; + case 0x1FAC: + return new int[] {0x1F64, 0x03B9}; + case 0x04A2: + return new int[] {0x04A3}; + case 0x1FAA: + return new int[] {0x1F62, 0x03B9}; + case 0x1FA6: + return new int[] {0x1F66, 0x03B9}; + case 0x1FA7: + return new int[] {0x1F67, 0x03B9}; + case 0x1FA4: + return new int[] {0x1F64, 0x03B9}; + case 0x1FA5: + return new int[] {0x1F65, 0x03B9}; + case 0x1FA8: + return new int[] {0x1F60, 0x03B9}; + case 0x1FA9: + return new int[] {0x1F61, 0x03B9}; + case 0x1FA2: + return new int[] {0x1F62, 0x03B9}; + case 0x1FA3: + return new int[] {0x1F63, 0x03B9}; + case 0x1FA0: + return new int[] {0x1F60, 0x03B9}; + case 0x1FA1: + return new int[] {0x1F61, 0x03B9}; + case 0x04B0: + return new int[] {0x04B1}; + case 0x04B4: + return new int[] {0x04B5}; + case 0x1FBC: + return new int[] {0x03B1, 0x03B9}; + case 0x04B2: + return new int[] {0x04B3}; + case 0x1FBA: + return new int[] {0x1F70}; + case 0x1FBB: + return new int[] {0x1F71}; + case 0x1FB7: + return new int[] {0x03B1, 0x0342, 0x03B9}; + case 0x1FB8: + return new int[] {0x1FB0}; + case 0x04AE: + return new int[] {0x04AF}; + case 0x1FB6: + return new int[] {0x03B1, 0x0342}; + case 0x1FB9: + return new int[] {0x1FB1}; + case 0x04AC: + return new int[] {0x04AD}; + case 0x1FB3: + return new int[] {0x03B1, 0x03B9}; + case 0x1FB4: + return new int[] {0x03AC, 0x03B9}; + case 0x04AA: + return new int[] {0x04AB}; + case 0x1FB2: + return new int[] {0x1F70, 0x03B9}; + case 0x1FAF: + return new int[] {0x1F67, 0x03B9}; + case 0x04A8: + return new int[] {0x04A9}; + case 0x1FAD: + return new int[] {0x1F65, 0x03B9}; + case 0x04A6: + return new int[] {0x04A7}; + case 0x1FAE: + return new int[] {0x1F66, 0x03B9}; + default: + return new int[] {codePoint}; + } + } + + /** + * ASCII space characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "ASCII space characters". + * @see RFC 3454, Appendix C.1.1 + */ + public static boolean prohibitionAsciiSpace(int codePoint) { + return codePoint == 0x0020 + + ; + } + + /** + * Non-ASCII space characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-ASCII space characters". + * @see RFC 3454, Appendix C.1.2 + */ + public static boolean prohibitionNonAsciiSpace(int codePoint) { + return codePoint == 0x00A0 + || codePoint == 0x1680 + || codePoint == 0x2000 + || codePoint == 0x2001 + || codePoint == 0x2002 + || codePoint == 0x2003 + || codePoint == 0x2004 + || codePoint == 0x2005 + || codePoint == 0x2006 + || codePoint == 0x2007 + || codePoint == 0x2008 + || codePoint == 0x2009 + || codePoint == 0x200A + || codePoint == 0x200B + || codePoint == 0x202F + || codePoint == 0x205F + || codePoint == 0x3000 + + ; + } + + /** + * ASCII control characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "ASCII control characters". + * @see RFC 3454, Appendix C.2.1 + */ + public static boolean prohibitionAsciiControl(int codePoint) { + return (codePoint >= 0x0000 && codePoint <= 0x001F) + || codePoint == 0x007F + + ; + } + + /** + * Non-ASCII control characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-ASCII control characters". + * @see RFC 3454, Appendix C.2.2 + */ + public static boolean prohibitionNonAsciiControl(int codePoint) { + return (codePoint >= 0x0080 && codePoint <= 0x009F) + || codePoint == 0x06DD + || codePoint == 0x070F + || codePoint == 0x180E + || codePoint == 0x200C + || codePoint == 0x200D + || codePoint == 0x2028 + || codePoint == 0x2029 + || codePoint == 0x2060 + || codePoint == 0x2061 + || codePoint == 0x2062 + || codePoint == 0x2063 + || (codePoint >= 0x206A && codePoint <= 0x206F) + || codePoint == 0xFEFF + || (codePoint >= 0xFFF9 && codePoint <= 0xFFFC) + || (codePoint >= 0x1D173 && codePoint <= 0x1D17A) + + ; + } + + /** + * Private use. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Private use". + * @see RFC 3454, Appendix C.3 + */ + public static boolean prohibitionPrivateUse(int codePoint) { + return (codePoint >= 0xE000 && codePoint <= 0xF8FF) + || (codePoint >= 0xF0000 && codePoint <= 0xFFFFD) + || (codePoint >= 0x100000 && codePoint <= 0x10FFFD) + + ; + } + + /** + * Non-character code points. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Non-character code points". + * @see RFC 3454, Appendix C.4 + */ + public static boolean prohibitionNonCharacterCodePoints(int codePoint) { + return (codePoint >= 0xFDD0 && codePoint <= 0xFDEF) + || (codePoint >= 0xFFFE && codePoint <= 0xFFFF) + || (codePoint >= 0x1FFFE && codePoint <= 0x1FFFF) + || (codePoint >= 0x2FFFE && codePoint <= 0x2FFFF) + || (codePoint >= 0x3FFFE && codePoint <= 0x3FFFF) + || (codePoint >= 0x4FFFE && codePoint <= 0x4FFFF) + || (codePoint >= 0x5FFFE && codePoint <= 0x5FFFF) + || (codePoint >= 0x6FFFE && codePoint <= 0x6FFFF) + || (codePoint >= 0x7FFFE && codePoint <= 0x7FFFF) + || (codePoint >= 0x8FFFE && codePoint <= 0x8FFFF) + || (codePoint >= 0x9FFFE && codePoint <= 0x9FFFF) + || (codePoint >= 0xAFFFE && codePoint <= 0xAFFFF) + || (codePoint >= 0xBFFFE && codePoint <= 0xBFFFF) + || (codePoint >= 0xCFFFE && codePoint <= 0xCFFFF) + || (codePoint >= 0xDFFFE && codePoint <= 0xDFFFF) + || (codePoint >= 0xEFFFE && codePoint <= 0xEFFFF) + || (codePoint >= 0xFFFFE && codePoint <= 0xFFFFF) + || (codePoint >= 0x10FFFE && codePoint <= 0x10FFFF) + + ; + } + + /** + * Surrogate codes. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Surrogate codes". + * @see RFC 3454, Appendix C.5 + */ + public static boolean prohibitionSurrogateCodes(int codePoint) { + return (codePoint >= 0xD800 && codePoint <= 0xDFFF) + + ; + } + + /** + * Inappropriate for plain text. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Inappropriate for plain text". + * @see RFC 3454, Appendix C.6 + */ + public static boolean prohibitionInappropriatePlainText(int codePoint) { + return codePoint == 0xFFF9 + || codePoint == 0xFFFA + || codePoint == 0xFFFB + || codePoint == 0xFFFC + || codePoint == 0xFFFD + + ; + } + + /** + * Inappropriate for canonical representation. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Inappropriate for canonical representation". + * @see RFC 3454, Appendix C.7 + */ + public static boolean prohibitionInappropriateCanonicalRepresentation(int codePoint) { + return (codePoint >= 0x2FF0 && codePoint <= 0x2FFB) + + ; + } + + /** + * Change display properties or are deprecated. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Change display properties or are deprecated". + * @see RFC 3454, Appendix C.8 + */ + public static boolean prohibitionChangeDisplayProperties(int codePoint) { + return codePoint == 0x0340 + || codePoint == 0x0341 + || codePoint == 0x200E + || codePoint == 0x200F + || codePoint == 0x202A + || codePoint == 0x202B + || codePoint == 0x202C + || codePoint == 0x202D + || codePoint == 0x202E + || codePoint == 0x206A + || codePoint == 0x206B + || codePoint == 0x206C + || codePoint == 0x206D + || codePoint == 0x206E + || codePoint == 0x206F + + ; + } + + /** + * Tagging characters. + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is "Tagging characters". + * @see RFC 3454, Appendix C.9 + */ + public static boolean prohibitionTaggingCharacters(int codePoint) { + return codePoint == 0xE0001 + || (codePoint >= 0xE0020 && codePoint <= 0xE007F) + + ; + } + + /** + * Characters with bidirectional property "R" or "AL". + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Characters with bidirectional property R or AL". + * @see RFC 3454, Appendix D.1 + */ + public static boolean bidirectionalPropertyRorAL(int codePoint) { + return codePoint == 0x05BE + || codePoint == 0x05C0 + || codePoint == 0x05C3 + || (codePoint >= 0x05D0 && codePoint <= 0x05EA) + || (codePoint >= 0x05F0 && codePoint <= 0x05F4) + || codePoint == 0x061B + || codePoint == 0x061F + || (codePoint >= 0x0621 && codePoint <= 0x063A) + || (codePoint >= 0x0640 && codePoint <= 0x064A) + || (codePoint >= 0x066D && codePoint <= 0x066F) + || (codePoint >= 0x0671 && codePoint <= 0x06D5) + || codePoint == 0x06DD + || (codePoint >= 0x06E5 && codePoint <= 0x06E6) + || (codePoint >= 0x06FA && codePoint <= 0x06FE) + || (codePoint >= 0x0700 && codePoint <= 0x070D) + || codePoint == 0x0710 + || (codePoint >= 0x0712 && codePoint <= 0x072C) + || (codePoint >= 0x0780 && codePoint <= 0x07A5) + || codePoint == 0x07B1 + || codePoint == 0x200F + || codePoint == 0xFB1D + || (codePoint >= 0xFB1F && codePoint <= 0xFB28) + || (codePoint >= 0xFB2A && codePoint <= 0xFB36) + || (codePoint >= 0xFB38 && codePoint <= 0xFB3C) + || codePoint == 0xFB3E + || (codePoint >= 0xFB40 && codePoint <= 0xFB41) + || (codePoint >= 0xFB43 && codePoint <= 0xFB44) + || (codePoint >= 0xFB46 && codePoint <= 0xFBB1) + || (codePoint >= 0xFBD3 && codePoint <= 0xFD3D) + || (codePoint >= 0xFD50 && codePoint <= 0xFD8F) + || (codePoint >= 0xFD92 && codePoint <= 0xFDC7) + || (codePoint >= 0xFDF0 && codePoint <= 0xFDFC) + || (codePoint >= 0xFE70 && codePoint <= 0xFE74) + || (codePoint >= 0xFE76 && codePoint <= 0xFEFC) + + ; + } + + /** + * Characters with bidirectional property "L". + * + * @param codePoint the character (Unicode code point) to be tested. + * @return {@code true} if the given {@code codePoint} is + * "Characters with bidirectional property L". + * @see RFC 3454, Appendix D.2 + */ + public static boolean bidirectionalPropertyL(int codePoint) { + return (codePoint >= 0x0041 && codePoint <= 0x005A) + || (codePoint >= 0x0061 && codePoint <= 0x007A) + || codePoint == 0x00AA + || codePoint == 0x00B5 + || codePoint == 0x00BA + || (codePoint >= 0x00C0 && codePoint <= 0x00D6) + || (codePoint >= 0x00D8 && codePoint <= 0x00F6) + || (codePoint >= 0x00F8 && codePoint <= 0x0220) + || (codePoint >= 0x0222 && codePoint <= 0x0233) + || (codePoint >= 0x0250 && codePoint <= 0x02AD) + || (codePoint >= 0x02B0 && codePoint <= 0x02B8) + || (codePoint >= 0x02BB && codePoint <= 0x02C1) + || (codePoint >= 0x02D0 && codePoint <= 0x02D1) + || (codePoint >= 0x02E0 && codePoint <= 0x02E4) + || codePoint == 0x02EE + || codePoint == 0x037A + || codePoint == 0x0386 + || (codePoint >= 0x0388 && codePoint <= 0x038A) + || codePoint == 0x038C + || (codePoint >= 0x038E && codePoint <= 0x03A1) + || (codePoint >= 0x03A3 && codePoint <= 0x03CE) + || (codePoint >= 0x03D0 && codePoint <= 0x03F5) + || (codePoint >= 0x0400 && codePoint <= 0x0482) + || (codePoint >= 0x048A && codePoint <= 0x04CE) + || (codePoint >= 0x04D0 && codePoint <= 0x04F5) + || (codePoint >= 0x04F8 && codePoint <= 0x04F9) + || (codePoint >= 0x0500 && codePoint <= 0x050F) + || (codePoint >= 0x0531 && codePoint <= 0x0556) + || (codePoint >= 0x0559 && codePoint <= 0x055F) + || (codePoint >= 0x0561 && codePoint <= 0x0587) + || codePoint == 0x0589 + || codePoint == 0x0903 + || (codePoint >= 0x0905 && codePoint <= 0x0939) + || (codePoint >= 0x093D && codePoint <= 0x0940) + || (codePoint >= 0x0949 && codePoint <= 0x094C) + || codePoint == 0x0950 + || (codePoint >= 0x0958 && codePoint <= 0x0961) + || (codePoint >= 0x0964 && codePoint <= 0x0970) + || (codePoint >= 0x0982 && codePoint <= 0x0983) + || (codePoint >= 0x0985 && codePoint <= 0x098C) + || (codePoint >= 0x098F && codePoint <= 0x0990) + || (codePoint >= 0x0993 && codePoint <= 0x09A8) + || (codePoint >= 0x09AA && codePoint <= 0x09B0) + || codePoint == 0x09B2 + || (codePoint >= 0x09B6 && codePoint <= 0x09B9) + || (codePoint >= 0x09BE && codePoint <= 0x09C0) + || (codePoint >= 0x09C7 && codePoint <= 0x09C8) + || (codePoint >= 0x09CB && codePoint <= 0x09CC) + || codePoint == 0x09D7 + || (codePoint >= 0x09DC && codePoint <= 0x09DD) + || (codePoint >= 0x09DF && codePoint <= 0x09E1) + || (codePoint >= 0x09E6 && codePoint <= 0x09F1) + || (codePoint >= 0x09F4 && codePoint <= 0x09FA) + || (codePoint >= 0x0A05 && codePoint <= 0x0A0A) + || (codePoint >= 0x0A0F && codePoint <= 0x0A10) + || (codePoint >= 0x0A13 && codePoint <= 0x0A28) + || (codePoint >= 0x0A2A && codePoint <= 0x0A30) + || (codePoint >= 0x0A32 && codePoint <= 0x0A33) + || (codePoint >= 0x0A35 && codePoint <= 0x0A36) + || (codePoint >= 0x0A38 && codePoint <= 0x0A39) + || (codePoint >= 0x0A3E && codePoint <= 0x0A40) + || (codePoint >= 0x0A59 && codePoint <= 0x0A5C) + || codePoint == 0x0A5E + || (codePoint >= 0x0A66 && codePoint <= 0x0A6F) + || (codePoint >= 0x0A72 && codePoint <= 0x0A74) + || codePoint == 0x0A83 + || (codePoint >= 0x0A85 && codePoint <= 0x0A8B) + || codePoint == 0x0A8D + || (codePoint >= 0x0A8F && codePoint <= 0x0A91) + || (codePoint >= 0x0A93 && codePoint <= 0x0AA8) + || (codePoint >= 0x0AAA && codePoint <= 0x0AB0) + || (codePoint >= 0x0AB2 && codePoint <= 0x0AB3) + || (codePoint >= 0x0AB5 && codePoint <= 0x0AB9) + || (codePoint >= 0x0ABD && codePoint <= 0x0AC0) + || codePoint == 0x0AC9 + || (codePoint >= 0x0ACB && codePoint <= 0x0ACC) + || codePoint == 0x0AD0 + || codePoint == 0x0AE0 + || (codePoint >= 0x0AE6 && codePoint <= 0x0AEF) + || (codePoint >= 0x0B02 && codePoint <= 0x0B03) + || (codePoint >= 0x0B05 && codePoint <= 0x0B0C) + || (codePoint >= 0x0B0F && codePoint <= 0x0B10) + || (codePoint >= 0x0B13 && codePoint <= 0x0B28) + || (codePoint >= 0x0B2A && codePoint <= 0x0B30) + || (codePoint >= 0x0B32 && codePoint <= 0x0B33) + || (codePoint >= 0x0B36 && codePoint <= 0x0B39) + || (codePoint >= 0x0B3D && codePoint <= 0x0B3E) + || codePoint == 0x0B40 + || (codePoint >= 0x0B47 && codePoint <= 0x0B48) + || (codePoint >= 0x0B4B && codePoint <= 0x0B4C) + || codePoint == 0x0B57 + || (codePoint >= 0x0B5C && codePoint <= 0x0B5D) + || (codePoint >= 0x0B5F && codePoint <= 0x0B61) + || (codePoint >= 0x0B66 && codePoint <= 0x0B70) + || codePoint == 0x0B83 + || (codePoint >= 0x0B85 && codePoint <= 0x0B8A) + || (codePoint >= 0x0B8E && codePoint <= 0x0B90) + || (codePoint >= 0x0B92 && codePoint <= 0x0B95) + || (codePoint >= 0x0B99 && codePoint <= 0x0B9A) + || codePoint == 0x0B9C + || (codePoint >= 0x0B9E && codePoint <= 0x0B9F) + || (codePoint >= 0x0BA3 && codePoint <= 0x0BA4) + || (codePoint >= 0x0BA8 && codePoint <= 0x0BAA) + || (codePoint >= 0x0BAE && codePoint <= 0x0BB5) + || (codePoint >= 0x0BB7 && codePoint <= 0x0BB9) + || (codePoint >= 0x0BBE && codePoint <= 0x0BBF) + || (codePoint >= 0x0BC1 && codePoint <= 0x0BC2) + || (codePoint >= 0x0BC6 && codePoint <= 0x0BC8) + || (codePoint >= 0x0BCA && codePoint <= 0x0BCC) + || codePoint == 0x0BD7 + || (codePoint >= 0x0BE7 && codePoint <= 0x0BF2) + || (codePoint >= 0x0C01 && codePoint <= 0x0C03) + || (codePoint >= 0x0C05 && codePoint <= 0x0C0C) + || (codePoint >= 0x0C0E && codePoint <= 0x0C10) + || (codePoint >= 0x0C12 && codePoint <= 0x0C28) + || (codePoint >= 0x0C2A && codePoint <= 0x0C33) + || (codePoint >= 0x0C35 && codePoint <= 0x0C39) + || (codePoint >= 0x0C41 && codePoint <= 0x0C44) + || (codePoint >= 0x0C60 && codePoint <= 0x0C61) + || (codePoint >= 0x0C66 && codePoint <= 0x0C6F) + || (codePoint >= 0x0C82 && codePoint <= 0x0C83) + || (codePoint >= 0x0C85 && codePoint <= 0x0C8C) + || (codePoint >= 0x0C8E && codePoint <= 0x0C90) + || (codePoint >= 0x0C92 && codePoint <= 0x0CA8) + || (codePoint >= 0x0CAA && codePoint <= 0x0CB3) + || (codePoint >= 0x0CB5 && codePoint <= 0x0CB9) + || codePoint == 0x0CBE + || (codePoint >= 0x0CC0 && codePoint <= 0x0CC4) + || (codePoint >= 0x0CC7 && codePoint <= 0x0CC8) + || (codePoint >= 0x0CCA && codePoint <= 0x0CCB) + || (codePoint >= 0x0CD5 && codePoint <= 0x0CD6) + || codePoint == 0x0CDE + || (codePoint >= 0x0CE0 && codePoint <= 0x0CE1) + || (codePoint >= 0x0CE6 && codePoint <= 0x0CEF) + || (codePoint >= 0x0D02 && codePoint <= 0x0D03) + || (codePoint >= 0x0D05 && codePoint <= 0x0D0C) + || (codePoint >= 0x0D0E && codePoint <= 0x0D10) + || (codePoint >= 0x0D12 && codePoint <= 0x0D28) + || (codePoint >= 0x0D2A && codePoint <= 0x0D39) + || (codePoint >= 0x0D3E && codePoint <= 0x0D40) + || (codePoint >= 0x0D46 && codePoint <= 0x0D48) + || (codePoint >= 0x0D4A && codePoint <= 0x0D4C) + || codePoint == 0x0D57 + || (codePoint >= 0x0D60 && codePoint <= 0x0D61) + || (codePoint >= 0x0D66 && codePoint <= 0x0D6F) + || (codePoint >= 0x0D82 && codePoint <= 0x0D83) + || (codePoint >= 0x0D85 && codePoint <= 0x0D96) + || (codePoint >= 0x0D9A && codePoint <= 0x0DB1) + || (codePoint >= 0x0DB3 && codePoint <= 0x0DBB) + || codePoint == 0x0DBD + || (codePoint >= 0x0DC0 && codePoint <= 0x0DC6) + || (codePoint >= 0x0DCF && codePoint <= 0x0DD1) + || (codePoint >= 0x0DD8 && codePoint <= 0x0DDF) + || (codePoint >= 0x0DF2 && codePoint <= 0x0DF4) + || (codePoint >= 0x0E01 && codePoint <= 0x0E30) + || (codePoint >= 0x0E32 && codePoint <= 0x0E33) + || (codePoint >= 0x0E40 && codePoint <= 0x0E46) + || (codePoint >= 0x0E4F && codePoint <= 0x0E5B) + || (codePoint >= 0x0E81 && codePoint <= 0x0E82) + || codePoint == 0x0E84 + || (codePoint >= 0x0E87 && codePoint <= 0x0E88) + || codePoint == 0x0E8A + || codePoint == 0x0E8D + || (codePoint >= 0x0E94 && codePoint <= 0x0E97) + || (codePoint >= 0x0E99 && codePoint <= 0x0E9F) + || (codePoint >= 0x0EA1 && codePoint <= 0x0EA3) + || codePoint == 0x0EA5 + || codePoint == 0x0EA7 + || (codePoint >= 0x0EAA && codePoint <= 0x0EAB) + || (codePoint >= 0x0EAD && codePoint <= 0x0EB0) + || (codePoint >= 0x0EB2 && codePoint <= 0x0EB3) + || codePoint == 0x0EBD + || (codePoint >= 0x0EC0 && codePoint <= 0x0EC4) + || codePoint == 0x0EC6 + || (codePoint >= 0x0ED0 && codePoint <= 0x0ED9) + || (codePoint >= 0x0EDC && codePoint <= 0x0EDD) + || (codePoint >= 0x0F00 && codePoint <= 0x0F17) + || (codePoint >= 0x0F1A && codePoint <= 0x0F34) + || codePoint == 0x0F36 + || codePoint == 0x0F38 + || (codePoint >= 0x0F3E && codePoint <= 0x0F47) + || (codePoint >= 0x0F49 && codePoint <= 0x0F6A) + || codePoint == 0x0F7F + || codePoint == 0x0F85 + || (codePoint >= 0x0F88 && codePoint <= 0x0F8B) + || (codePoint >= 0x0FBE && codePoint <= 0x0FC5) + || (codePoint >= 0x0FC7 && codePoint <= 0x0FCC) + || codePoint == 0x0FCF + || (codePoint >= 0x1000 && codePoint <= 0x1021) + || (codePoint >= 0x1023 && codePoint <= 0x1027) + || (codePoint >= 0x1029 && codePoint <= 0x102A) + || codePoint == 0x102C + || codePoint == 0x1031 + || codePoint == 0x1038 + || (codePoint >= 0x1040 && codePoint <= 0x1057) + || (codePoint >= 0x10A0 && codePoint <= 0x10C5) + || (codePoint >= 0x10D0 && codePoint <= 0x10F8) + || codePoint == 0x10FB + || (codePoint >= 0x1100 && codePoint <= 0x1159) + || (codePoint >= 0x115F && codePoint <= 0x11A2) + || (codePoint >= 0x11A8 && codePoint <= 0x11F9) + || (codePoint >= 0x1200 && codePoint <= 0x1206) + || (codePoint >= 0x1208 && codePoint <= 0x1246) + || codePoint == 0x1248 + || (codePoint >= 0x124A && codePoint <= 0x124D) + || (codePoint >= 0x1250 && codePoint <= 0x1256) + || codePoint == 0x1258 + || (codePoint >= 0x125A && codePoint <= 0x125D) + || (codePoint >= 0x1260 && codePoint <= 0x1286) + || codePoint == 0x1288 + || (codePoint >= 0x128A && codePoint <= 0x128D) + || (codePoint >= 0x1290 && codePoint <= 0x12AE) + || codePoint == 0x12B0 + || (codePoint >= 0x12B2 && codePoint <= 0x12B5) + || (codePoint >= 0x12B8 && codePoint <= 0x12BE) + || codePoint == 0x12C0 + || (codePoint >= 0x12C2 && codePoint <= 0x12C5) + || (codePoint >= 0x12C8 && codePoint <= 0x12CE) + || (codePoint >= 0x12D0 && codePoint <= 0x12D6) + || (codePoint >= 0x12D8 && codePoint <= 0x12EE) + || (codePoint >= 0x12F0 && codePoint <= 0x130E) + || codePoint == 0x1310 + || (codePoint >= 0x1312 && codePoint <= 0x1315) + || (codePoint >= 0x1318 && codePoint <= 0x131E) + || (codePoint >= 0x1320 && codePoint <= 0x1346) + || (codePoint >= 0x1348 && codePoint <= 0x135A) + || (codePoint >= 0x1361 && codePoint <= 0x137C) + || (codePoint >= 0x13A0 && codePoint <= 0x13F4) + || (codePoint >= 0x1401 && codePoint <= 0x1676) + || (codePoint >= 0x1681 && codePoint <= 0x169A) + || (codePoint >= 0x16A0 && codePoint <= 0x16F0) + || (codePoint >= 0x1700 && codePoint <= 0x170C) + || (codePoint >= 0x170E && codePoint <= 0x1711) + || (codePoint >= 0x1720 && codePoint <= 0x1731) + || (codePoint >= 0x1735 && codePoint <= 0x1736) + || (codePoint >= 0x1740 && codePoint <= 0x1751) + || (codePoint >= 0x1760 && codePoint <= 0x176C) + || (codePoint >= 0x176E && codePoint <= 0x1770) + || (codePoint >= 0x1780 && codePoint <= 0x17B6) + || (codePoint >= 0x17BE && codePoint <= 0x17C5) + || (codePoint >= 0x17C7 && codePoint <= 0x17C8) + || (codePoint >= 0x17D4 && codePoint <= 0x17DA) + || codePoint == 0x17DC + || (codePoint >= 0x17E0 && codePoint <= 0x17E9) + || (codePoint >= 0x1810 && codePoint <= 0x1819) + || (codePoint >= 0x1820 && codePoint <= 0x1877) + || (codePoint >= 0x1880 && codePoint <= 0x18A8) + || (codePoint >= 0x1E00 && codePoint <= 0x1E9B) + || (codePoint >= 0x1EA0 && codePoint <= 0x1EF9) + || (codePoint >= 0x1F00 && codePoint <= 0x1F15) + || (codePoint >= 0x1F18 && codePoint <= 0x1F1D) + || (codePoint >= 0x1F20 && codePoint <= 0x1F45) + || (codePoint >= 0x1F48 && codePoint <= 0x1F4D) + || (codePoint >= 0x1F50 && codePoint <= 0x1F57) + || codePoint == 0x1F59 + || codePoint == 0x1F5B + || codePoint == 0x1F5D + || (codePoint >= 0x1F5F && codePoint <= 0x1F7D) + || (codePoint >= 0x1F80 && codePoint <= 0x1FB4) + || (codePoint >= 0x1FB6 && codePoint <= 0x1FBC) + || codePoint == 0x1FBE + || (codePoint >= 0x1FC2 && codePoint <= 0x1FC4) + || (codePoint >= 0x1FC6 && codePoint <= 0x1FCC) + || (codePoint >= 0x1FD0 && codePoint <= 0x1FD3) + || (codePoint >= 0x1FD6 && codePoint <= 0x1FDB) + || (codePoint >= 0x1FE0 && codePoint <= 0x1FEC) + || (codePoint >= 0x1FF2 && codePoint <= 0x1FF4) + || (codePoint >= 0x1FF6 && codePoint <= 0x1FFC) + || codePoint == 0x200E + || codePoint == 0x2071 + || codePoint == 0x207F + || codePoint == 0x2102 + || codePoint == 0x2107 + || (codePoint >= 0x210A && codePoint <= 0x2113) + || codePoint == 0x2115 + || (codePoint >= 0x2119 && codePoint <= 0x211D) + || codePoint == 0x2124 + || codePoint == 0x2126 + || codePoint == 0x2128 + || (codePoint >= 0x212A && codePoint <= 0x212D) + || (codePoint >= 0x212F && codePoint <= 0x2131) + || (codePoint >= 0x2133 && codePoint <= 0x2139) + || (codePoint >= 0x213D && codePoint <= 0x213F) + || (codePoint >= 0x2145 && codePoint <= 0x2149) + || (codePoint >= 0x2160 && codePoint <= 0x2183) + || (codePoint >= 0x2336 && codePoint <= 0x237A) + || codePoint == 0x2395 + || (codePoint >= 0x249C && codePoint <= 0x24E9) + || (codePoint >= 0x3005 && codePoint <= 0x3007) + || (codePoint >= 0x3021 && codePoint <= 0x3029) + || (codePoint >= 0x3031 && codePoint <= 0x3035) + || (codePoint >= 0x3038 && codePoint <= 0x303C) + || (codePoint >= 0x3041 && codePoint <= 0x3096) + || (codePoint >= 0x309D && codePoint <= 0x309F) + || (codePoint >= 0x30A1 && codePoint <= 0x30FA) + || (codePoint >= 0x30FC && codePoint <= 0x30FF) + || (codePoint >= 0x3105 && codePoint <= 0x312C) + || (codePoint >= 0x3131 && codePoint <= 0x318E) + || (codePoint >= 0x3190 && codePoint <= 0x31B7) + || (codePoint >= 0x31F0 && codePoint <= 0x321C) + || (codePoint >= 0x3220 && codePoint <= 0x3243) + || (codePoint >= 0x3260 && codePoint <= 0x327B) + || (codePoint >= 0x327F && codePoint <= 0x32B0) + || (codePoint >= 0x32C0 && codePoint <= 0x32CB) + || (codePoint >= 0x32D0 && codePoint <= 0x32FE) + || (codePoint >= 0x3300 && codePoint <= 0x3376) + || (codePoint >= 0x337B && codePoint <= 0x33DD) + || (codePoint >= 0x33E0 && codePoint <= 0x33FE) + || (codePoint >= 0x3400 && codePoint <= 0x4DB5) + || (codePoint >= 0x4E00 && codePoint <= 0x9FA5) + || (codePoint >= 0xA000 && codePoint <= 0xA48C) + || (codePoint >= 0xAC00 && codePoint <= 0xD7A3) + || (codePoint >= 0xD800 && codePoint <= 0xFA2D) + || (codePoint >= 0xFA30 && codePoint <= 0xFA6A) + || (codePoint >= 0xFB00 && codePoint <= 0xFB06) + || (codePoint >= 0xFB13 && codePoint <= 0xFB17) + || (codePoint >= 0xFF21 && codePoint <= 0xFF3A) + || (codePoint >= 0xFF41 && codePoint <= 0xFF5A) + || (codePoint >= 0xFF66 && codePoint <= 0xFFBE) + || (codePoint >= 0xFFC2 && codePoint <= 0xFFC7) + || (codePoint >= 0xFFCA && codePoint <= 0xFFCF) + || (codePoint >= 0xFFD2 && codePoint <= 0xFFD7) + || (codePoint >= 0xFFDA && codePoint <= 0xFFDC) + || (codePoint >= 0x10300 && codePoint <= 0x1031E) + || (codePoint >= 0x10320 && codePoint <= 0x10323) + || (codePoint >= 0x10330 && codePoint <= 0x1034A) + || (codePoint >= 0x10400 && codePoint <= 0x10425) + || (codePoint >= 0x10428 && codePoint <= 0x1044D) + || (codePoint >= 0x1D000 && codePoint <= 0x1D0F5) + || (codePoint >= 0x1D100 && codePoint <= 0x1D126) + || (codePoint >= 0x1D12A && codePoint <= 0x1D166) + || (codePoint >= 0x1D16A && codePoint <= 0x1D172) + || (codePoint >= 0x1D183 && codePoint <= 0x1D184) + || (codePoint >= 0x1D18C && codePoint <= 0x1D1A9) + || (codePoint >= 0x1D1AE && codePoint <= 0x1D1DD) + || (codePoint >= 0x1D400 && codePoint <= 0x1D454) + || (codePoint >= 0x1D456 && codePoint <= 0x1D49C) + || (codePoint >= 0x1D49E && codePoint <= 0x1D49F) + || codePoint == 0x1D4A2 + || (codePoint >= 0x1D4A5 && codePoint <= 0x1D4A6) + || (codePoint >= 0x1D4A9 && codePoint <= 0x1D4AC) + || (codePoint >= 0x1D4AE && codePoint <= 0x1D4B9) + || codePoint == 0x1D4BB + || (codePoint >= 0x1D4BD && codePoint <= 0x1D4C0) + || (codePoint >= 0x1D4C2 && codePoint <= 0x1D4C3) + || (codePoint >= 0x1D4C5 && codePoint <= 0x1D505) + || (codePoint >= 0x1D507 && codePoint <= 0x1D50A) + || (codePoint >= 0x1D50D && codePoint <= 0x1D514) + || (codePoint >= 0x1D516 && codePoint <= 0x1D51C) + || (codePoint >= 0x1D51E && codePoint <= 0x1D539) + || (codePoint >= 0x1D53B && codePoint <= 0x1D53E) + || (codePoint >= 0x1D540 && codePoint <= 0x1D544) + || codePoint == 0x1D546 + || (codePoint >= 0x1D54A && codePoint <= 0x1D550) + || (codePoint >= 0x1D552 && codePoint <= 0x1D6A3) + || (codePoint >= 0x1D6A8 && codePoint <= 0x1D7C9) + || (codePoint >= 0x20000 && codePoint <= 0x2A6D6) + || (codePoint >= 0x2F800 && codePoint <= 0x2FA1D) + || (codePoint >= 0xF0000 && codePoint <= 0xFFFFD) + || (codePoint >= 0x100000 && codePoint <= 0x10FFFD) + + ; + } + +} diff --git a/stringprep/src/main/java/com/ongres/stringprep/package-info.java b/stringprep/src/main/java/com/ongres/stringprep/package-info.java new file mode 100644 index 0000000..28d8ddc --- /dev/null +++ b/stringprep/src/main/java/com/ongres/stringprep/package-info.java @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +/** + * Preparation of Internationalized Strings ("stringprep"). + */ + +package com.ongres.stringprep; diff --git a/stringprep/src/main/java9/module-info.java b/stringprep/src/main/java9/module-info.java new file mode 100644 index 0000000..35977e8 --- /dev/null +++ b/stringprep/src/main/java9/module-info.java @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +module com.ongres.stringprep { + exports com.ongres.stringprep; + uses com.ongres.stringprep.Profile; +} \ No newline at end of file diff --git a/stringprep/src/test/java/com/ongres/stringprep/StringPrepTest.java b/stringprep/src/test/java/com/ongres/stringprep/StringPrepTest.java deleted file mode 100644 index 96336ef..0000000 --- a/stringprep/src/test/java/com/ongres/stringprep/StringPrepTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2019, OnGres. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package com.ongres.stringprep; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.ongres.stringprep.StringPrep; -import java.io.IOException; -import java.util.Arrays; - -import org.junit.Test; - -public class StringPrepTest { - - @Test - public void testBidirectionalTables() throws Exception { - //Property R or AL - assertTrue(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("061B", 16))); - assertTrue(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("FE76", 16))); - assertTrue(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("FEFC", 16))); - assertTrue(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("FE71", 16))); - assertFalse(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("066C", 16))); - assertFalse(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("06D6", 16))); - assertFalse(StringPrep.bidirectionalPropertyRorAL(Integer.parseInt("0041", 16))); - - //Property L - assertTrue(StringPrep.bidirectionalPropertyL(Integer.parseInt("1D4A2", 16))); - assertTrue(StringPrep.bidirectionalPropertyL(Integer.parseInt("20000", 16))); - assertTrue(StringPrep.bidirectionalPropertyL(Integer.parseInt("2A6D6", 16))); - assertTrue(StringPrep.bidirectionalPropertyL(Integer.parseInt("10FFFC", 16))); - assertFalse(StringPrep.bidirectionalPropertyL(Integer.parseInt("0040", 16))); - assertFalse(StringPrep.bidirectionalPropertyL(Integer.parseInt("005B", 16))); - assertFalse(StringPrep.bidirectionalPropertyL(Integer.parseInt("037B", 16))); - - //Properties R or AL and L - try { - StringPrep.bidirectional(Arrays.asList(Integer.parseInt("200E", 16))); - fail(); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().startsWith("Prohibited codepoint 8206 at position 0")); - } - try { - StringPrep.bidirectional(Arrays.asList(Integer.parseInt("061B", 16), - Integer.parseInt("1D4A2", 16))); - } catch (IllegalArgumentException e) { - assertEquals("Prohibited string with RandALCat and LCat", e.getMessage()); - } - try { - StringPrep.bidirectional(Arrays.asList(Integer.parseInt("061B", 16), - Integer.parseInt("0000", 16))); - } catch (IllegalArgumentException e) { - assertEquals( - "The string contains any RandALCat character but a RandALCat character " - + "is not the first and the last characters", - e.getMessage()); - } - } - - @Test - public void testMappingTables() throws Exception { - //Map to nothing - assertTrue(StringPrep.mapToNothing(Integer.parseInt("00AD", 16))); - assertFalse(StringPrep.mapToNothing(Integer.parseInt("0100", 16))); - assertTrue(StringPrep.mapToNothing(Integer.parseInt("FE0F", 16))); - - //Map NFKC - int[] result = StringPrep.mapUsedWithNfkc(Integer.parseInt("00DF", 16)); - assertEquals(2, result.length); - assertEquals(Integer.parseInt("0073", 16), result[0]); - assertEquals(Integer.parseInt("0073", 16), result[1]); - result = StringPrep.mapUsedWithNfkc(Integer.parseInt("33C6", 16)); - assertEquals(4, result.length); - assertEquals(Integer.parseInt("0063", 16), result[0]); - assertEquals(Integer.parseInt("2215", 16), result[1]); - assertEquals(Integer.parseInt("006B", 16), result[2]); - assertEquals(Integer.parseInt("0067", 16), result[3]); - result = StringPrep.mapUsedWithNfkc(Integer.parseInt("03B0", 16)); - assertEquals(3, result.length); - assertEquals(Integer.parseInt("03C5", 16), result[0]); - assertEquals(Integer.parseInt("0308", 16), result[1]); - assertEquals(Integer.parseInt("0301", 16), result[2]); - result = StringPrep.mapUsedWithNfkc(Integer.parseInt("1D7BB", 16)); - assertEquals(1, result.length); - assertEquals(Integer.parseInt("03C3", 16), result[0]); - result = StringPrep.mapUsedWithNfkc(Integer.parseInt("1D7BC", 16)); - assertEquals(1, result.length); - assertEquals(Integer.parseInt("1D7BC", 16), result[0]); - - //Map NoNormalization - result = StringPrep.mapUsedWithNoNormalization(Integer.parseInt("10425", 16)); - assertEquals(1, result.length); - assertEquals(Integer.parseInt("1044D", 16), result[0]); - result = StringPrep.mapUsedWithNoNormalization(Integer.parseInt("0130", 16)); - assertEquals(2, result.length); - assertEquals(Integer.parseInt("0069", 16), result[0]); - assertEquals(Integer.parseInt("0307", 16), result[1]); - result = StringPrep.mapUsedWithNoNormalization(Integer.parseInt("0390", 16)); - assertEquals(3, result.length); - assertEquals(Integer.parseInt("03B9", 16), result[0]); - assertEquals(Integer.parseInt("0308", 16), result[1]); - assertEquals(Integer.parseInt("0301", 16), result[2]); - result = StringPrep.mapUsedWithNoNormalization(Integer.parseInt("10426", 16)); - assertEquals(1, result.length); - assertEquals(Integer.parseInt("10426", 16), result[0]); - } - - @Test - public void testProhibitionTables() throws NumberFormatException, IOException { - //AsciiSpace - assertFalse(StringPrep.prohibitionAsciiSpace(Integer.parseInt("00A0", 16))); - assertTrue(StringPrep.prohibitionAsciiSpace(Integer.parseInt("0020", 16))); - //NonAsciiSpace - assertTrue(StringPrep.prohibitionNonAsciiSpace(Integer.parseInt("00A0", 16))); - assertFalse(StringPrep.prohibitionNonAsciiSpace(Integer.parseInt("0020", 16))); - //AsciiControl - assertTrue(StringPrep.prohibitionAsciiControl(Integer.parseInt("0000", 16))); - assertTrue(StringPrep.prohibitionAsciiControl(Integer.parseInt("0001", 16))); - assertTrue(StringPrep.prohibitionAsciiControl(Integer.parseInt("001F", 16))); - assertTrue(StringPrep.prohibitionAsciiControl(Integer.parseInt("007F", 16))); - assertFalse(StringPrep.prohibitionAsciiControl(Integer.parseInt("0020", 16))); - //NonAsciiControl - assertTrue(StringPrep.prohibitionNonAsciiControl(Integer.parseInt("1D173", 16))); - assertTrue(StringPrep.prohibitionNonAsciiControl(Integer.parseInt("1D17A", 16))); - assertTrue(StringPrep.prohibitionNonAsciiControl(Integer.parseInt("1D175", 16))); - assertTrue(StringPrep.prohibitionNonAsciiControl(Integer.parseInt("2028", 16))); - assertFalse(StringPrep.prohibitionNonAsciiControl(Integer.parseInt("0000", 16))); - //PrivateUse - assertTrue(StringPrep.prohibitionPrivateUse(Integer.parseInt("100000", 16))); - assertTrue(StringPrep.prohibitionPrivateUse(Integer.parseInt("10000A", 16))); - assertTrue(StringPrep.prohibitionPrivateUse(Integer.parseInt("10FFFD", 16))); - assertFalse(StringPrep.prohibitionPrivateUse(Integer.parseInt("FFFF", 16))); - //NonCharacterCodePoints - assertTrue(StringPrep.prohibitionNonCharacterCodePoints(Integer.parseInt("10FFFE", 16))); - assertTrue(StringPrep.prohibitionNonCharacterCodePoints(Integer.parseInt("10FFFF", 16))); - assertTrue(StringPrep.prohibitionNonCharacterCodePoints(Integer.parseInt("FDEE", 16))); - assertFalse(StringPrep.prohibitionNonCharacterCodePoints(Integer.parseInt("10FFFD", 16))); - //SurrogateCodes - assertTrue(StringPrep.prohibitionSurrogateCodes(Integer.parseInt("D800", 16))); - assertTrue(StringPrep.prohibitionSurrogateCodes(Integer.parseInt("D805", 16))); - assertTrue(StringPrep.prohibitionSurrogateCodes(Integer.parseInt("DFFF", 16))); - assertFalse(StringPrep.prohibitionSurrogateCodes(Integer.parseInt("10FFFD", 16))); - //InappropiatePlainText - assertTrue(StringPrep.prohibitionInappropriatePlainText(Integer.parseInt("FFF9", 16))); - assertFalse(StringPrep.prohibitionInappropriatePlainText(Integer.parseInt("100000", 16))); - //InappropriateCanonicalRepresentation - assertTrue(StringPrep.prohibitionInappropriateCanonicalRepresentation( - Integer.parseInt("2FF0", 16))); - assertTrue(StringPrep.prohibitionInappropriateCanonicalRepresentation( - Integer.parseInt("2FFB", 16))); - assertTrue(StringPrep.prohibitionInappropriateCanonicalRepresentation( - Integer.parseInt("2FF3", 16))); - assertFalse(StringPrep.prohibitionInappropriateCanonicalRepresentation( - Integer.parseInt("100000", 16))); - //ChangeDisplayProperties - assertTrue(StringPrep.prohibitionChangeDisplayProperties(Integer.parseInt("200E", 16))); - assertFalse(StringPrep.prohibitionChangeDisplayProperties(Integer.parseInt("2FF0", 16))); - //TaggingCharacters - assertTrue(StringPrep.prohibitionTaggingCharacters(Integer.parseInt("E0001", 16))); - assertTrue(StringPrep.prohibitionTaggingCharacters(Integer.parseInt("E0020", 16))); - assertTrue(StringPrep.prohibitionTaggingCharacters(Integer.parseInt("E002F", 16))); - assertTrue(StringPrep.prohibitionTaggingCharacters(Integer.parseInt("E007F", 16))); - assertFalse(StringPrep.prohibitionTaggingCharacters(Integer.parseInt("D800", 16))); - } - - @Test - public void testUnicodeRepertoires() throws NumberFormatException, IOException { - assertTrue(StringPrep.unassignedCodePoints(Integer.parseInt("1D49D", 16))); - assertTrue(StringPrep.unassignedCodePoints(Integer.parseInt("E0080", 16))); - assertTrue(StringPrep.unassignedCodePoints(Integer.parseInt("E2FFD", 16))); - assertTrue(StringPrep.unassignedCodePoints(Integer.parseInt("EFFFD", 16))); - assertFalse(StringPrep.unassignedCodePoints(Integer.parseInt("E0001", 16))); - } -} diff --git a/stringprep/src/test/java/test/stringprep/ProfileTest.java b/stringprep/src/test/java/test/stringprep/ProfileTest.java new file mode 100644 index 0000000..bf22678 --- /dev/null +++ b/stringprep/src/test/java/test/stringprep/ProfileTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2021 OnGres, Inc. + * SPDX-License-Identifier: BSD-2-Clause + */ + +package test.stringprep; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.EnumSet; +import java.util.Locale; +import java.util.Set; +import java.util.stream.IntStream; + +import com.ongres.stringprep.Option; +import com.ongres.stringprep.Profile; +import com.ongres.stringprep.Stringprep; +import com.ongres.stringprep.Tables; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +class ProfileTest { + + @Test + void nullProvider() { + assertThrows(NullPointerException.class, () -> Stringprep.getProvider(null)); + assertThrows(IllegalArgumentException.class, () -> Stringprep.getProvider("")); + } + + @Test + void testAllOptions() { + Profile profile = () -> EnumSet.allOf(Option.class); + char[] example1 = "A\u00ADDⅨ".toCharArray(); + assertArrayEquals("adix".toCharArray(), profile.prepareStored(example1)); + assertArrayEquals("adix".toCharArray(), profile.prepareQuery(example1)); + } + + @Test + void testNoneOptions() { + Profile profile = () -> EnumSet.noneOf(Option.class); + char[] example1 = "A\u00AD\u200A\u0BBCZ".toCharArray(); + assertArrayEquals(example1, profile.prepareQuery(example1)); + IllegalArgumentException storedIllegal = + assertThrows(IllegalArgumentException.class, () -> profile.prepareStored(example1)); + assertEquals("Unassigned code point \"0x0BBC\"", storedIllegal.getMessage()); + } + + @ParameterizedTest + @CsvSource(value = {"℻,FAX", "⑳,20", "㎓,GHz", "A\u00ADD ⑳,AD 20"}) + void testNormKcOptions(String value, String expected) { + Profile profile = () -> EnumSet.of(Option.NORMALIZE_KC, Option.MAP_TO_NOTHING); + char[] valueChars = value.toCharArray(); + char[] expectedChars = expected.toCharArray(); + assertArrayEquals(expectedChars, profile.prepareStored(valueChars)); + assertArrayEquals(expectedChars, profile.prepareQuery(valueChars)); + } + + @Test + void testAdditionalProhibitionsOptions() { + Profile profile = new Profile() { + @Override + public Set