├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── jarRepositories.xml ├── kotlinScripting.xml ├── misc.xml └── vcs.xml ├── .vs ├── VSWorkspaceState.json └── slnx.sqlite ├── LICENSE.txt ├── README.md ├── build.gradle.kts ├── documents └── 変換対応表.xlsx ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kanaria_core ├── .gitignore ├── Cargo.toml ├── build.gradle.kts ├── ret.txt ├── src │ ├── char.rs │ ├── constants.rs │ ├── lib.rs │ ├── string │ │ ├── ext.rs │ │ ├── mod.rs │ │ ├── params.rs │ │ └── string.rs │ └── utils │ │ ├── ascii.rs │ │ ├── chars.rs │ │ ├── ext.rs │ │ ├── kana.rs │ │ ├── mod.rs │ │ └── width.rs └── tests │ ├── ascii.rs │ ├── example_sentence.rs │ ├── kana.rs │ └── narrow_wide.rs ├── kanaria_dotnet ├── .gitignore ├── KanariaDotNet │ ├── FodyWeavers.xml │ ├── KanariaDotNet.csproj │ ├── KanariaDotNet.nuspec │ ├── costura32 │ │ └── .gitkeep │ ├── costura64 │ │ └── .gitkeep │ └── src │ │ ├── ConvertTarget.cs │ │ ├── UCSString.cs │ │ └── Utils │ │ ├── AsciiUtils.cs │ │ ├── KanaUtils.cs │ │ └── WidthUtils.cs ├── KanariaSample │ ├── KanariaSample.csproj │ └── src │ │ └── Program.cs ├── KanariaTest │ ├── ExampleText.Designer.cs │ ├── ExampleText.resx │ ├── KanariaTest.csproj │ └── src │ │ ├── Benchmark.cs │ │ ├── ExampleSentenceTest.cs │ │ └── External │ │ └── Kanaxs.cs ├── build.gradle.kts ├── kanaria_dotnet.sln └── kanaria_dotnet.sln.DotSettings ├── kanaria_extern ├── .gitignore ├── Cargo.toml ├── build.gradle.kts └── src │ ├── lib.rs │ └── utf16 │ ├── checker.rs │ ├── converter.rs │ └── mod.rs ├── kanaria_jvm ├── .gitignore ├── build.gradle.kts └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── kanaria │ │ │ ├── KanariaLoader.kt │ │ │ ├── UcsString.kt │ │ │ ├── exception │ │ │ ├── NotLoadingJniException.kt │ │ │ └── UnsupportedPlatformException.kt │ │ │ └── utils │ │ │ ├── AsciiUtils.kt │ │ │ ├── KanaUtils.kt │ │ │ └── WidthUtils.kt │ ├── resources │ │ └── com │ │ │ └── kanaria │ │ │ └── platform.xml │ └── rust │ │ ├── .cargo │ │ └── config │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ ├── checker.rs │ │ ├── converter.rs │ │ └── lib.rs │ └── test │ └── kotlin │ └── com │ └── kanaria │ ├── ExampleSentenceTest.kt │ └── KanariaLoaderTest.kt ├── libs └── .gitignore ├── settings.gradle.kts └── setup ├── install_android_compiler_x86_64.sh └── install_compiler_x86_64.sh /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Gradle CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Set up JDK 17 13 | uses: actions/setup-java@v4 14 | with: 15 | distribution: 'temurin' 16 | java-version: 17 17 | - name: Set up Rust 18 | run: | 19 | rustup toolchain install stable --profile minimal 20 | rustup default stable 21 | - name: Grant execute permission for install_compiler_x86_64.sh 22 | run: chmod +x ./setup/install_compiler_x86_64.sh 23 | - name: Set up BuildTools 24 | run: sudo ./setup/install_compiler_x86_64.sh 25 | - name: Grant execute permission for install_android_compiler_x86_64.sh 26 | run: chmod +x ./setup/install_android_compiler_x86_64.sh 27 | - name: Set up AndroidNDK BuildTools 28 | run: ./setup/install_android_compiler_x86_64.sh 29 | - name: Grant execute permission for gradlew 30 | run: chmod +x gradlew 31 | - name: Test with Gradle 32 | run: ./gradlew test --info 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | local.properties 2 | 3 | # Created by https://www.gitignore.io/api/gradle 4 | # Edit at https://www.gitignore.io/?templates=gradle 5 | 6 | ### Gradle ### 7 | .gradle 8 | build/ 9 | 10 | # Ignore Gradle GUI config 11 | gradle-app.setting 12 | 13 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 14 | !gradle-wrapper.jar 15 | 16 | # Cache of project 17 | .gradletasknamecache 18 | 19 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 20 | gradle/wrapper/gradle-wrapper.properties 21 | 22 | ### Gradle Patch ### 23 | **/build/ 24 | 25 | # End of https://www.gitignore.io/api/gradle 26 | 27 | 28 | 29 | # Created by https://www.gitignore.io/api/intellij 30 | # Edit at https://www.gitignore.io/?templates=intellij 31 | 32 | ### Intellij ### 33 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 34 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 35 | 36 | # User-specific stuff 37 | .idea/**/workspace.xml 38 | .idea/**/tasks.xml 39 | .idea/**/usage.statistics.xml 40 | .idea/**/dictionaries 41 | .idea/**/shelf 42 | .idea/**/git_toolbox_*.xml 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | .idea/modules.xml 65 | .idea/*.iml 66 | .idea/modules 67 | 68 | # CMake 69 | cmake-build-*/ 70 | 71 | # Mongo Explorer plugin 72 | .idea/**/mongoSettings.xml 73 | 74 | # File-based project format 75 | *.iws 76 | 77 | # IntelliJ 78 | out/ 79 | 80 | # mpeltonen/sbt-idea plugin 81 | .idea_modules/ 82 | 83 | # JIRA plugin 84 | atlassian-ide-plugin.xml 85 | 86 | # Cursive Clojure plugin 87 | .idea/replstate.xml 88 | 89 | # Crashlytics plugin (for Android Studio and IntelliJ) 90 | com_crashlytics_export_strings.xml 91 | crashlytics.properties 92 | crashlytics-build.properties 93 | fabric.properties 94 | 95 | # Editor-based Rest Client 96 | .idea/httpRequests 97 | 98 | # Android studio 3.1+ serialized cache file 99 | .idea/caches/build_file_checksums.ser 100 | 101 | ### Intellij Patch ### 102 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 103 | 104 | *.iml 105 | modules.xml 106 | .idea/misc.xml 107 | *.ipr 108 | 109 | # Sonarlint plugin 110 | .idea/sonarlint 111 | 112 | # End of https://www.gitignore.io/api/intellij 113 | 114 | log.txt 115 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/kotlinScripting.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 13 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.vs/VSWorkspaceState.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExpandedNodes": [ 3 | "", 4 | "\\kanaria_dotnet", 5 | "\\kanaria_dotnet\\KanariaDotNet" 6 | ], 7 | "SelectedNode": "\\kanaria_dotnet\\KanariaDotNet\\KanariaDotNet.csproj", 8 | "PreviewInSolutionExplorer": false 9 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samunohito/kanaria/9c2a6237d5a523f372b50d956671251710d5f4ac/.vs/slnx.sqlite -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 samu no hito 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Kanaria 2 | ==== 3 | 4 | このライブラリは、ひらがな・カタカナ、半角・全角の相互変換や判別を始めとした機能を提供します。 5 | 6 | ![Gradle CI](https://github.com/samunohito/kanaria/workflows/Gradle%20CI/badge.svg?branch=develop) 7 | 8 | ## Description 9 | 10 | 変換処理は次のものをご用意しています。 11 | 12 | - 変換処理 13 | - ひらがな<->カタカナの変換 14 | - 半角<->全角の変換(ガ<->ガのように、濁音記号の結合も行います) 15 | - アルファベットの大文字<->小文字変換 16 | 17 | 判定処理は次のものをご用意しています。
18 | ひらがなを除き、それぞれ半角のみ、全角のみ、半角・全角区別なしの物があります。 19 | - 判定処理 20 | - ひらがな 21 | - カタカナ 22 | - 数字 23 | - アルファベット 24 | - 記号 25 | 26 | ## Demo / Usage 27 | 28 | UCSStrに文字列を読み込ませ、変換先の設定を行い(この例だとカタカナに変換後、さらに半角に変換)、
29 | Stringとして吐き出しているサンプルです。 30 | ```rust 31 | let source = "吾輩は😺猫である😺"; 32 | let expect = "吾輩ハ😺猫デアル😺"; 33 | 34 | assert_eq!(expect, UCSStr::from_str(source).katakana().narrow().to_string()); 35 | ``` 36 | 37 | また、上記のようにメソッドチェーンによる連続した変換設定はできませんが、
38 | 次のような形でも変換できます。
39 | ```rust 40 | use kanaria::string::UCSStr; 41 | use kanaria::string::ConvertType::Katakana; 42 | use kanaria::utils::ConvertTarget; 43 | use kanaria::string::ConvertType; 44 | 45 | let target = vec!['あ', 'い', 'う', 'え', 'お']; 46 | let result = UCSStr::convert(target.as_slice(), ConvertType::Katakana, ConvertTarget::ALL); 47 | 48 | assert_eq!(result, vec!['ア', 'イ', 'ウ', 'エ', 'オ']); 49 | ``` 50 | この例は、半角文字を全角文字に変換しています。
51 | この形式での変換は生ポインタ(\*mut u16など)への書き込みを行うことができます。
52 | 連続での変換はせず、なおかつ速度を求める場合はこちらのほうが便利です。
53 |
54 | ちなみに、他言語向けのラッパーライブラリも別途ご用意しています。
55 | 以下はC#の例です(VB.NETからも同じ要領で使用できるはずです)。 56 | ```C# 57 | var katakana = "吾輩ハ😺猫デアル😺"; 58 | var hiragana = "吾輩は😺猫である😺"; 59 | Assert.AreEqual(katakana, UcsString.From(hiragana).Katakana().ToString()); 60 | Assert.AreEqual(hiragana, UcsString.From(katakana).Hiragana().ToString()); 61 | ``` 62 | 63 | ## Installation 64 | 各言語で使用されるパッケージマネージャやビルドツール等からインストールできます。 65 | 66 | Rust( https://crates.io/crates/kanaria ) 67 | ```toml:Cargo.toml 68 | [dependencies] 69 | kanaria = "0.2.0" 70 | ``` 71 |
72 | 73 | C#( https://www.nuget.org/packages/Kanaria.Net/ ) 74 | ```bat 75 | PM> Install-Package Kanaria.Net -Version 0.2.0 76 | ``` 77 |
78 | 79 | Maven( https://bintray.com/sam-osamu/maven/com.kanaria.kanaria_jvm ) 80 | ```xml:pom.xml 81 | 82 | com.kanaria 83 | kanaria_jvm 84 | 0.2.0 85 | pom 86 | 87 | ``` 88 |
89 | 90 | Gradle( https://bintray.com/sam-osamu/maven/com.kanaria.kanaria_jvm ) 91 | ```gradle:build.gradle 92 | compile 'com.kanaria:kanaria_jvm:0.2.0' 93 | ``` 94 | 95 | ## API 96 | 次のページをご参照ください(これはRust向けのものです)。
97 | https://docs.rs/kanaria/0.2.0/kanaria/
98 |
99 | RustDocのようにサンプルを交えての記載まではできていませんが、
100 | 各言語のラッパー関数にも同様の関数コメントをご用意しています。
101 | 102 | ## Licence 103 | [MIT](https://opensource.org/licenses/mit-license.php) 104 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | jcenter() 5 | mavenCentral() 6 | } 7 | } 8 | 9 | tasks { 10 | create("release") { 11 | group = "summary" 12 | bindChildProjectsTasks(this, "rustBuildRelease", childProjects.values) 13 | } 14 | 15 | create("test") { 16 | group = "summary" 17 | dependsOn(getByName("release")) 18 | 19 | val exclude = listOf("kanaria_dotnet", "kanaria_extern", "kanaria_jvm") 20 | bindChildProjectsTasks(this, "rustTestRelease", childProjects.values.filter { pj -> !exclude.any { pj.name.contains(it) } }) 21 | bindChildProjectsTasks(this, "testClasses", childProjects.values) 22 | } 23 | } 24 | 25 | fun bindChildProjectsTasks(rootTask: Task, findByName: String, childProjects: Iterable) { 26 | childProjects.forEach { childProject -> 27 | childProject.gradle.projectsEvaluated { 28 | childProject.tasks.findByName(findByName)?.also { 29 | rootTask.dependsOn(it) 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /documents/変換対応表.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samunohito/kanaria/9c2a6237d5a523f372b50d956671251710d5f4ac/documents/変換対応表.xlsx -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samunohito/kanaria/9c2a6237d5a523f372b50d956671251710d5f4ac/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 01 14:26:11 JST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /kanaria_core/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/rust 2 | # Edit at https://www.gitignore.io/?templates=rust 3 | 4 | ### Rust ### 5 | # Generated by Cargo 6 | # will have compiled files and executables 7 | /target/ 8 | 9 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 10 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 11 | Cargo.lock 12 | 13 | # These are backup files generated by rustfmt 14 | **/*.rs.bk 15 | 16 | # End of https://www.gitignore.io/api/rust -------------------------------------------------------------------------------- /kanaria_core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kanaria" 3 | version = "0.2.1" 4 | authors = ["samunohito <46447427+samunohito@users.noreply.github.com>"] 5 | edition = "2021" 6 | 7 | repository = "https://github.com/samunohito/kanaria" 8 | readme = "../README.md" 9 | description = "This library provides functions such as hiragana, katakana, half-width and full-width mutual conversion and discrimination." 10 | license = "MIT" 11 | 12 | keywords = ["wide", "narrow", "hiragana", "katakana"] 13 | 14 | exclude = [ 15 | "tests/*" 16 | ] 17 | 18 | [dependencies] 19 | bitflags = "2.6.0" 20 | 21 | [lib] 22 | name = "kanaria" 23 | path = "src/lib.rs" 24 | 25 | -------------------------------------------------------------------------------- /kanaria_core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.osm.gradle.plugins.rustic") version "0.2.7" 3 | } 4 | 5 | rustic { 6 | projectSettings.projectLocation(projectDir.toString()) 7 | defaultConfig.defaultOptions.jobs(8) 8 | } -------------------------------------------------------------------------------- /kanaria_core/src/char.rs: -------------------------------------------------------------------------------- 1 | use std::char; 2 | use std::fmt::Debug; 3 | 4 | pub trait UCSChar: Debug + Sized + Default + Copy + Ord + Eq { 5 | /// NULLを表します。 6 | const NULL: Self; 7 | 8 | /// 対象がlow以上high以下かどうかを判定します。 9 | /// 10 | /// # Examples 11 | /// 12 | /// ``` 13 | /// use kanaria::UCSChar; 14 | /// use kanaria::constants::*; 15 | /// 16 | /// // (0x0041 >= 0x0041) && (0x0041 <= 0x005A) 17 | /// let true_case = 'A'.is_in_range(NARROW_ASCII_LATIN_UPPER_CASE_A, NARROW_ASCII_LATIN_UPPER_CASE_Z); 18 | /// assert_eq!(true_case, true); 19 | /// 20 | /// // (0x0061 >= 0x0041) && (0x0061 <= 0x005A) 21 | /// let false_case = 'a'.is_in_range(NARROW_ASCII_LATIN_UPPER_CASE_A, NARROW_ASCII_LATIN_UPPER_CASE_Z); 22 | /// assert_eq!(false_case, false); 23 | /// ``` 24 | fn is_in_range(&self, low: u32, high: u32) -> bool; 25 | 26 | /// searchの中に対象を含むかどうかを判定します。 27 | /// 28 | /// # Examples 29 | /// 30 | /// ``` 31 | /// use kanaria::UCSChar; 32 | /// use kanaria::constants::*; 33 | /// 34 | /// let true_case = 'A'.is_contains(&[NARROW_ASCII_LATIN_UPPER_CASE_A, NARROW_ASCII_LATIN_UPPER_CASE_B, NARROW_ASCII_LATIN_UPPER_CASE_C]); 35 | /// assert_eq!(true_case, true); 36 | /// 37 | /// let false_case = 'D'.is_contains(&[NARROW_ASCII_LATIN_UPPER_CASE_A, NARROW_ASCII_LATIN_UPPER_CASE_B, NARROW_ASCII_LATIN_UPPER_CASE_C]); 38 | /// assert_eq!(false_case, false); 39 | /// ``` 40 | fn is_contains(&self, search: &[u32]) -> bool; 41 | 42 | /// targetと対象が同値であるかどうかを判定します。 43 | /// 44 | /// # Examples 45 | /// 46 | /// ``` 47 | /// use kanaria::UCSChar; 48 | /// use kanaria::constants::*; 49 | /// 50 | /// let true_case = 'A'.is_match(NARROW_ASCII_LATIN_UPPER_CASE_A); 51 | /// assert_eq!(true_case, true); 52 | /// 53 | /// let false_case = 'A'.is_match(NARROW_ASCII_LATIN_LOWER_CASE_A); 54 | /// assert_eq!(false_case, false); 55 | /// ``` 56 | fn is_match(&self, target: u32) -> bool; 57 | 58 | /// サロゲートペアであるかどうかを判定します。 59 | /// 60 | /// # Examples 61 | /// 62 | /// ``` 63 | /// use kanaria::UCSChar; 64 | /// 65 | /// // 𩸽(ほっけ)の上位サロゲート 66 | /// assert_eq!(0xD867u16.is_surrogate(), true); 67 | /// 68 | /// // 𩸽(ほっけ)の下位サロゲート 69 | /// assert_eq!(0xDE3Du16.is_surrogate(), true); 70 | /// 71 | /// // ひらがなの「あ」 72 | /// assert_eq!(0x3042u16.is_surrogate(), false); 73 | /// ``` 74 | fn is_surrogate(&self) -> bool; 75 | 76 | /// 上位サロゲートであるかどうかを判定します。 77 | /// 78 | /// # Examples 79 | /// 80 | /// ``` 81 | /// use kanaria::UCSChar; 82 | /// 83 | /// // 𩸽(ほっけ)の上位サロゲート 84 | /// assert_eq!(0xD867u16.is_high_surrogate(), true); 85 | /// 86 | /// // 𩸽(ほっけ)の下位サロゲート 87 | /// assert_eq!(0xDE3Du16.is_high_surrogate(), false); 88 | /// 89 | /// // ひらがなの「あ」 90 | /// assert_eq!(0x3042u16.is_high_surrogate(), false); 91 | /// ``` 92 | fn is_high_surrogate(&self) -> bool; 93 | 94 | /// 下位サロゲートであるかどうかを判定します。 95 | /// 96 | /// # Examples 97 | /// 98 | /// ``` 99 | /// use kanaria::UCSChar; 100 | /// 101 | /// // 𩸽(ほっけ)の上位サロゲート 102 | /// assert_eq!(0xD867u16.is_low_surrogate(), false); 103 | /// 104 | /// // 𩸽(ほっけ)の下位サロゲート 105 | /// assert_eq!(0xDE3Du16.is_low_surrogate(), true); 106 | /// 107 | /// // ひらがなの「あ」 108 | /// assert_eq!(0x3042u16.is_low_surrogate(), false); 109 | /// ``` 110 | fn is_low_surrogate(&self) -> bool; 111 | 112 | /// null文字であるかどうかを判定します。 113 | /// 114 | /// # Examples 115 | /// 116 | /// ``` 117 | /// use kanaria::UCSChar; 118 | /// 119 | /// assert_eq!(char::NULL.is_null(), true); 120 | /// assert_eq!('a'.is_null(), false); 121 | /// ``` 122 | fn is_null(&self) -> bool; 123 | 124 | /// 対象にvalueの値を加算した文字を取得します。 125 | /// 126 | /// # Examples 127 | /// 128 | /// ``` 129 | /// use kanaria::UCSChar; 130 | /// use kanaria::constants::*; 131 | /// 132 | /// let ret = 'あ'.addition(0x0060); 133 | /// assert_eq!(ret, 'ア'); 134 | /// ``` 135 | fn addition(&self, value: u32) -> Self; 136 | 137 | /// 対象からvalueの値を減算した文字を取得します。 138 | /// 139 | /// # Examples 140 | /// 141 | /// ``` 142 | /// use kanaria::UCSChar; 143 | /// use kanaria::constants::*; 144 | /// 145 | /// let ret = 'ア'.subtraction(0x0060); 146 | /// assert_eq!(ret, 'あ'); 147 | /// ``` 148 | fn subtraction(&self, value: u32) -> Self; 149 | 150 | /// 値をUnicodeスカラ値に変換します。 151 | /// 152 | /// # Examples 153 | /// 154 | /// ``` 155 | /// use kanaria::UCSChar; 156 | /// use kanaria::constants::*; 157 | /// 158 | /// let ret = 'A'.as_scalar(); 159 | /// assert_eq!(ret, NARROW_ASCII_LATIN_UPPER_CASE_A); 160 | /// ``` 161 | fn as_scalar(&self) -> u32; 162 | 163 | /// Unicodeスカラ値から値を取り込みます。 164 | /// 165 | /// # Examples 166 | /// 167 | /// ``` 168 | /// use kanaria::UCSChar; 169 | /// use kanaria::constants::*; 170 | /// 171 | /// let ret = char::from_scalar(NARROW_ASCII_LATIN_UPPER_CASE_A); 172 | /// assert_eq!(ret, 'A'); 173 | /// ``` 174 | fn from_scalar(value: T) -> Self where T: UCSChar; 175 | } 176 | 177 | impl UCSChar for char { 178 | const NULL: char = 0 as char; 179 | 180 | #[inline] 181 | fn is_in_range(&self, low: u32, high: u32) -> bool { 182 | let target_trans = *self as u32; 183 | target_trans >= low && target_trans <= high 184 | } 185 | 186 | #[inline] 187 | fn is_contains(&self, search: &[u32]) -> bool { 188 | let target_trans = *self as u32; 189 | search.contains(&target_trans) 190 | } 191 | 192 | #[inline] 193 | fn is_match(&self, target: u32) -> bool { 194 | (*self as u32) == target 195 | } 196 | 197 | #[inline] 198 | fn is_surrogate(&self) -> bool { 199 | Self::is_high_surrogate(self) || Self::is_low_surrogate(self) 200 | } 201 | 202 | #[inline] 203 | fn is_high_surrogate(&self) -> bool { 204 | let scalar = self.as_scalar(); 205 | 0xD800 <= scalar && scalar < 0xDC00 206 | } 207 | 208 | #[inline] 209 | fn is_low_surrogate(&self) -> bool { 210 | let scalar = self.as_scalar(); 211 | 0xDC00 <= scalar && scalar < 0xE000 212 | } 213 | 214 | #[inline] 215 | fn is_null(&self) -> bool { 216 | *self == Self::NULL 217 | } 218 | 219 | #[inline] 220 | fn addition(&self, value: u32) -> Self { 221 | unsafe { char::from_u32_unchecked((*self as u32) + value) } 222 | } 223 | 224 | #[inline] 225 | fn subtraction(&self, value: u32) -> Self { 226 | unsafe { char::from_u32_unchecked((*self as u32) - value) } 227 | } 228 | 229 | #[inline] 230 | fn as_scalar(&self) -> u32 { 231 | *self as u32 232 | } 233 | 234 | #[inline] 235 | fn from_scalar(value: T) -> Self where T: UCSChar { 236 | unsafe { char::from_u32_unchecked(value.as_scalar()) } 237 | } 238 | } 239 | 240 | impl UCSChar for u16 { 241 | const NULL: u16 = 0; 242 | 243 | #[inline] 244 | fn is_in_range(&self, low: u32, high: u32) -> bool { 245 | let target_trans = *self as u32; 246 | target_trans >= low && target_trans <= high 247 | } 248 | 249 | #[inline] 250 | fn is_contains(&self, search: &[u32]) -> bool { 251 | let target_trans = *self as u32; 252 | search.contains(&target_trans) 253 | } 254 | 255 | #[inline] 256 | fn is_match(&self, target: u32) -> bool { 257 | (*self as u32) == target 258 | } 259 | 260 | #[inline] 261 | fn is_surrogate(&self) -> bool { 262 | Self::is_high_surrogate(self) || Self::is_low_surrogate(self) 263 | } 264 | 265 | #[inline] 266 | fn is_high_surrogate(&self) -> bool { 267 | let scalar = self.as_scalar(); 268 | 0xD800 <= scalar && scalar < 0xDC00 269 | } 270 | 271 | #[inline] 272 | fn is_low_surrogate(&self) -> bool { 273 | let scalar = self.as_scalar(); 274 | 0xDC00 <= scalar && scalar < 0xE000 275 | } 276 | 277 | #[inline] 278 | fn is_null(&self) -> bool { 279 | *self == Self::NULL 280 | } 281 | 282 | #[inline] 283 | fn addition(&self, value: u32) -> Self { 284 | ((*self as u32) + value) as u16 285 | } 286 | 287 | #[inline] 288 | fn subtraction(&self, value: u32) -> Self { 289 | ((*self as u32) - value) as u16 290 | } 291 | 292 | #[inline] 293 | fn as_scalar(&self) -> u32 { 294 | *self as u32 295 | } 296 | 297 | #[inline] 298 | fn from_scalar(value: T) -> Self where T: UCSChar { 299 | value.as_scalar() as u16 300 | } 301 | } 302 | 303 | impl UCSChar for u32 { 304 | const NULL: u32 = 0; 305 | 306 | #[inline] 307 | fn is_in_range(&self, low: u32, high: u32) -> bool { 308 | let target_trans = *self; 309 | target_trans >= low && target_trans <= high 310 | } 311 | 312 | #[inline] 313 | fn is_contains(&self, search: &[u32]) -> bool { 314 | search.contains(self) 315 | } 316 | 317 | #[inline] 318 | fn is_match(&self, target: u32) -> bool { 319 | (*self) == target 320 | } 321 | 322 | #[inline] 323 | fn is_surrogate(&self) -> bool { 324 | Self::is_high_surrogate(self) || Self::is_low_surrogate(self) 325 | } 326 | 327 | #[inline] 328 | fn is_high_surrogate(&self) -> bool { 329 | let scalar = self.as_scalar(); 330 | 0xD800 <= scalar && scalar < 0xDC00 331 | } 332 | 333 | #[inline] 334 | fn is_low_surrogate(&self) -> bool { 335 | let scalar = self.as_scalar(); 336 | 0xDC00 <= scalar && scalar < 0xE000 337 | } 338 | 339 | #[inline] 340 | fn is_null(&self) -> bool { 341 | *self == Self::NULL 342 | } 343 | 344 | #[inline] 345 | fn addition(&self, value: u32) -> Self { 346 | ((*self) + value) as u32 347 | } 348 | 349 | #[inline] 350 | fn subtraction(&self, value: u32) -> Self { 351 | ((*self) - value) as u32 352 | } 353 | 354 | #[inline] 355 | fn as_scalar(&self) -> u32 { 356 | *self 357 | } 358 | 359 | #[inline] 360 | fn from_scalar(value: T) -> Self where T: UCSChar { 361 | value.as_scalar() 362 | } 363 | } -------------------------------------------------------------------------------- /kanaria_core/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate bitflags; 3 | 4 | pub use self::char::UCSChar; 5 | 6 | pub mod constants; 7 | pub mod utils; 8 | pub mod char; 9 | pub mod string; 10 | -------------------------------------------------------------------------------- /kanaria_core/src/string/ext.rs: -------------------------------------------------------------------------------- 1 | use crate::UCSChar; 2 | use crate::string::string::UCSStr; 3 | 4 | impl Clone for UCSStr where T: UCSChar { 5 | fn clone(&self) -> Self { 6 | Self { 7 | target: self.target.clone(), 8 | convert_params: self.convert_params.clone(), 9 | } 10 | } 11 | 12 | fn clone_from(&mut self, source: &Self) { 13 | *self = source.clone() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kanaria_core/src/string/mod.rs: -------------------------------------------------------------------------------- 1 | mod params; 2 | mod string; 3 | mod ext; 4 | 5 | pub use self::string::UCSStr; 6 | pub use self::params::ConvertParameter; 7 | pub use self::params::ConvertType; 8 | -------------------------------------------------------------------------------- /kanaria_core/src/string/params.rs: -------------------------------------------------------------------------------- 1 | use crate::utils::ConvertTarget; 2 | 3 | #[derive(Debug, PartialEq, Copy, Clone)] 4 | pub enum ConvertType { 5 | /// アルファベット大文字に変換します。 6 | UpperCase, 7 | /// アルファベット小文字に変換します。 8 | LowerCase, 9 | /// ひらがなに変換します。 10 | Hiragana, 11 | /// カタカナに変換します。 12 | Katakana, 13 | /// 半角文字に変換します。 14 | Narrow, 15 | /// 全角文字に変換します。 16 | Wide, 17 | /// 変換操作を行いません。 18 | None, 19 | } 20 | 21 | #[derive(Debug, PartialEq, Copy, Clone)] 22 | pub struct ConvertParameter { 23 | /// 変換先の種別を保持します。 24 | pub convert_type: ConvertType, 25 | /// 半角・全角変換の対象を設定します。 26 | /// 大文字・小文字、ひらがな・かたかな変換時は使用されません。 27 | pub width_convert_target: ConvertTarget, 28 | } 29 | 30 | impl ConvertParameter { 31 | /// 変換時のパラメータを設定します。 32 | pub fn from(convert_type: ConvertType, width_convert_target: ConvertTarget) -> Self { 33 | Self { 34 | convert_type, 35 | width_convert_target, 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /kanaria_core/src/utils/ascii.rs: -------------------------------------------------------------------------------- 1 | use crate::UCSChar; 2 | use crate::constants::*; 3 | 4 | const UNICODE_OFFSET_ALPHABET_UPPER_LOWER: u32 = 0x0020; 5 | 6 | pub struct AsciiUtils; 7 | 8 | impl AsciiUtils { 9 | /// ASCII文字かどうかを判定します。 10 | /// 11 | /// # Examples 12 | /// 13 | /// ``` 14 | /// use kanaria::utils::AsciiUtils; 15 | /// 16 | /// assert_eq!(AsciiUtils::is_ascii('a'), true); 17 | /// assert_eq!(AsciiUtils::is_ascii('A'), true); 18 | /// assert_eq!(AsciiUtils::is_ascii('@'), true); 19 | /// assert_eq!(AsciiUtils::is_ascii('0'), true); 20 | /// assert_eq!(AsciiUtils::is_ascii('a'), true); 21 | /// assert_eq!(AsciiUtils::is_ascii('A'), true); 22 | /// assert_eq!(AsciiUtils::is_ascii('@'), true); 23 | /// assert_eq!(AsciiUtils::is_ascii('0'), true); 24 | /// 25 | /// assert_eq!(AsciiUtils::is_ascii('あ'), false); 26 | /// ``` 27 | #[inline] 28 | pub fn is_ascii(target: T) -> bool where T: UCSChar { 29 | AsciiUtils::is_narrow_ascii(target) || AsciiUtils::is_wide_ascii(target) 30 | } 31 | 32 | /// 半角ASCII文字かどうかを判定します。 33 | /// 34 | /// # Examples 35 | /// 36 | /// ``` 37 | /// use kanaria::utils::AsciiUtils; 38 | /// 39 | /// assert_eq!(AsciiUtils::is_narrow_ascii('a'), true); 40 | /// assert_eq!(AsciiUtils::is_narrow_ascii('A'), true); 41 | /// assert_eq!(AsciiUtils::is_narrow_ascii('@'), true); 42 | /// assert_eq!(AsciiUtils::is_narrow_ascii('0'), true); 43 | /// 44 | /// assert_eq!(AsciiUtils::is_narrow_ascii('a'), false); 45 | /// assert_eq!(AsciiUtils::is_narrow_ascii('A'), false); 46 | /// assert_eq!(AsciiUtils::is_narrow_ascii('@'), false); 47 | /// assert_eq!(AsciiUtils::is_narrow_ascii('0'), false); 48 | /// ``` 49 | #[inline] 50 | pub fn is_narrow_ascii(target: T) -> bool where T: UCSChar { 51 | AsciiUtils::is_narrow_lower_case(target) || 52 | AsciiUtils::is_narrow_upper_case(target) || 53 | AsciiUtils::is_narrow_ascii_symbol(target) || 54 | AsciiUtils::is_narrow_number(target) 55 | } 56 | 57 | /// 全角ASCII文字かどうかを判定します。 58 | /// 59 | /// # Examples 60 | /// 61 | /// ``` 62 | /// use kanaria::utils::AsciiUtils; 63 | /// 64 | /// assert_eq!(AsciiUtils::is_wide_ascii('a'), true); 65 | /// assert_eq!(AsciiUtils::is_wide_ascii('A'), true); 66 | /// assert_eq!(AsciiUtils::is_wide_ascii('@'), true); 67 | /// assert_eq!(AsciiUtils::is_wide_ascii('0'), true); 68 | /// 69 | /// assert_eq!(AsciiUtils::is_wide_ascii('a'), false); 70 | /// assert_eq!(AsciiUtils::is_wide_ascii('A'), false); 71 | /// assert_eq!(AsciiUtils::is_wide_ascii('@'), false); 72 | /// assert_eq!(AsciiUtils::is_wide_ascii('0'), false); 73 | /// ``` 74 | #[inline] 75 | pub fn is_wide_ascii(target: T) -> bool where T: UCSChar { 76 | AsciiUtils::is_wide_lower_case(target) || 77 | AsciiUtils::is_wide_upper_case(target) || 78 | AsciiUtils::is_wide_ascii_symbol(target) || 79 | AsciiUtils::is_wide_number(target) 80 | } 81 | 82 | /// 英字の小文字かどうかを判定します。 83 | /// 半角・全角は区別しません。 84 | /// 85 | /// # Examples 86 | /// 87 | /// ``` 88 | /// use kanaria::utils::AsciiUtils; 89 | /// 90 | /// assert_eq!(AsciiUtils::is_lower_case('a'), true); 91 | /// assert_eq!(AsciiUtils::is_lower_case('a'), true); 92 | /// 93 | /// assert_eq!(AsciiUtils::is_lower_case('A'), false); 94 | /// assert_eq!(AsciiUtils::is_lower_case('A'), false); 95 | /// ``` 96 | #[inline] 97 | pub fn is_lower_case(target: T) -> bool where T: UCSChar { 98 | AsciiUtils::is_narrow_lower_case(target) || AsciiUtils::is_wide_lower_case(target) 99 | } 100 | 101 | /// 半角英字の小文字かどうかを判定します。 102 | /// 103 | /// # Examples 104 | /// 105 | /// ``` 106 | /// use kanaria::utils::AsciiUtils; 107 | /// 108 | /// assert_eq!(AsciiUtils::is_narrow_lower_case('a'), true); 109 | /// 110 | /// assert_eq!(AsciiUtils::is_narrow_lower_case('a'), false); 111 | /// assert_eq!(AsciiUtils::is_narrow_lower_case('A'), false); 112 | /// assert_eq!(AsciiUtils::is_narrow_lower_case('A'), false); 113 | /// ``` 114 | #[inline] 115 | pub fn is_narrow_lower_case(target: T) -> bool where T: UCSChar { 116 | target.is_in_range(NARROW_ASCII_LATIN_LOWER_CASE_A, NARROW_ASCII_LATIN_LOWER_CASE_Z) 117 | } 118 | 119 | /// 全角英字の小文字かどうかを判定します。 120 | /// 121 | /// # Examples 122 | /// 123 | /// ``` 124 | /// use kanaria::utils::AsciiUtils; 125 | /// 126 | /// assert_eq!(AsciiUtils::is_wide_lower_case('a'), true); 127 | /// 128 | /// assert_eq!(AsciiUtils::is_wide_lower_case('a'), false); 129 | /// assert_eq!(AsciiUtils::is_wide_lower_case('A'), false); 130 | /// assert_eq!(AsciiUtils::is_wide_lower_case('A'), false); 131 | /// ``` 132 | #[inline] 133 | pub fn is_wide_lower_case(target: T) -> bool where T: UCSChar { 134 | target.is_in_range(WIDE_ASCII_LATIN_LOWER_CASE_A, WIDE_ASCII_LATIN_LOWER_CASE_Z) 135 | } 136 | 137 | /// 英字の大文字かどうかを判定します。 138 | /// 半角・全角は区別しません。 139 | /// 140 | /// # Examples 141 | /// 142 | /// ``` 143 | /// use kanaria::utils::AsciiUtils; 144 | /// 145 | /// assert_eq!(AsciiUtils::is_upper_case('A'), true); 146 | /// assert_eq!(AsciiUtils::is_upper_case('A'), true); 147 | /// 148 | /// assert_eq!(AsciiUtils::is_upper_case('1'), false); 149 | /// assert_eq!(AsciiUtils::is_upper_case('1'), false); 150 | /// ``` 151 | #[inline] 152 | pub fn is_upper_case(target: T) -> bool where T: UCSChar { 153 | AsciiUtils::is_narrow_upper_case(target) || AsciiUtils::is_wide_upper_case(target) 154 | } 155 | 156 | /// 半角英字の大文字かどうかを判定します。 157 | /// 158 | /// # Examples 159 | /// 160 | /// ``` 161 | /// use kanaria::utils::AsciiUtils; 162 | /// 163 | /// assert_eq!(AsciiUtils::is_narrow_upper_case('A'), true); 164 | /// 165 | /// assert_eq!(AsciiUtils::is_narrow_upper_case('A'), false); 166 | /// assert_eq!(AsciiUtils::is_narrow_upper_case('a'), false); 167 | /// assert_eq!(AsciiUtils::is_narrow_upper_case('a'), false); 168 | /// ``` 169 | #[inline] 170 | pub fn is_narrow_upper_case(target: T) -> bool where T: UCSChar { 171 | target.is_in_range(NARROW_ASCII_LATIN_UPPER_CASE_A, NARROW_ASCII_LATIN_UPPER_CASE_Z) 172 | } 173 | 174 | /// 全角英字の大文字かどうかを判定します。 175 | /// 176 | /// # Examples 177 | /// 178 | /// ``` 179 | /// use kanaria::utils::AsciiUtils; 180 | /// 181 | /// assert_eq!(AsciiUtils::is_wide_upper_case('A'), true); 182 | /// 183 | /// assert_eq!(AsciiUtils::is_wide_upper_case('A'), false); 184 | /// assert_eq!(AsciiUtils::is_wide_upper_case('a'), false); 185 | /// assert_eq!(AsciiUtils::is_wide_upper_case('a'), false); 186 | /// ``` 187 | #[inline] 188 | pub fn is_wide_upper_case(target: T) -> bool where T: UCSChar { 189 | target.is_in_range(WIDE_ASCII_LATIN_UPPER_CASE_A, WIDE_ASCII_LATIN_UPPER_CASE_Z) 190 | } 191 | 192 | /// 記号かどうかを判定します。 193 | /// 半角・全角は区別しません。 194 | /// なお、ASCIIコードに属する記号のみを判定します。 195 | /// 196 | /// # Examples 197 | /// 198 | /// ``` 199 | /// use kanaria::utils::AsciiUtils; 200 | /// 201 | /// assert_eq!(AsciiUtils::is_ascii_symbol('@'), true); 202 | /// assert_eq!(AsciiUtils::is_ascii_symbol('@'), true); 203 | /// 204 | /// // かな文字で使用されるような記号は半角・全角問わずtrueとならない(例は濁音記号) 205 | /// assert_eq!(AsciiUtils::is_ascii_symbol('゙'), false); 206 | /// assert_eq!(AsciiUtils::is_ascii_symbol('゙'), false); 207 | /// ``` 208 | #[inline] 209 | pub fn is_ascii_symbol(target: T) -> bool where T: UCSChar { 210 | AsciiUtils::is_narrow_ascii_symbol(target) || AsciiUtils::is_wide_ascii_symbol(target) 211 | } 212 | 213 | /// 半角記号かどうかを判定します。 214 | /// なお、ASCIIコードに属する記号のみを判定します。 215 | /// 216 | /// # Examples 217 | /// 218 | /// ``` 219 | /// use kanaria::utils::AsciiUtils; 220 | /// 221 | /// assert_eq!(AsciiUtils::is_narrow_ascii_symbol('@'), true); 222 | /// 223 | /// assert_eq!(AsciiUtils::is_narrow_ascii_symbol('@'), false); 224 | /// 225 | /// // かな文字で使用されるような記号は半角・全角問わずtrueとならない(例は濁音記号) 226 | /// assert_eq!(AsciiUtils::is_narrow_ascii_symbol('゙'), false); 227 | /// assert_eq!(AsciiUtils::is_narrow_ascii_symbol('゙'), false); 228 | /// ``` 229 | #[inline] 230 | pub fn is_narrow_ascii_symbol(target: T) -> bool where T: UCSChar { 231 | target.is_in_range(NARROW_ASCII_SYMBOL_SPACE, NARROW_ASCII_SYMBOL_SOLIDUS) || 232 | target.is_in_range(NARROW_ASCII_SYMBOL_COLON, NARROW_ASCII_SYMBOL_COMMERCIAL_AT) || 233 | target.is_in_range(NARROW_ASCII_SYMBOL_LEFT_SQUARE_BRACKET, NARROW_ASCII_SYMBOL_GRAVE_ACCENT) || 234 | target.is_in_range(NARROW_ASCII_SYMBOL_LEFT_CURLY_BRACKET, NARROW_ASCII_SYMBOL_TILDE) 235 | } 236 | 237 | /// 全角記号かどうかを判定します。 238 | /// なお、ASCIIコードに属する記号のみを判定します。 239 | /// 240 | /// # Examples 241 | /// 242 | /// ``` 243 | /// use kanaria::utils::AsciiUtils; 244 | /// 245 | /// assert_eq!(AsciiUtils::is_wide_ascii_symbol('@'), true); 246 | /// 247 | /// assert_eq!(AsciiUtils::is_wide_ascii_symbol('@'), false); 248 | /// 249 | /// // かな文字で使用されるような記号は半角・全角問わずtrueとならない(例は濁音記号) 250 | /// assert_eq!(AsciiUtils::is_wide_ascii_symbol('゙'), false); 251 | /// assert_eq!(AsciiUtils::is_wide_ascii_symbol('゙'), false); 252 | /// ``` 253 | #[inline] 254 | pub fn is_wide_ascii_symbol(target: T) -> bool where T: UCSChar { 255 | target.is_in_range(WIDE_ASCII_SYMBOL_EXCLAMATION_MARK, WIDE_ASCII_SYMBOL_SOLIDUS) || 256 | target.is_in_range(WIDE_ASCII_SYMBOL_COLON, WIDE_ASCII_SYMBOL_COMMERCIAL_AT) || 257 | target.is_in_range(WIDE_ASCII_SYMBOL_LEFT_SQUARE_BRACKET, WIDE_ASCII_SYMBOL_GRAVE_ACCENT) || 258 | target.is_in_range(WIDE_ASCII_SYMBOL_LEFT_CURLY_BRACKET, WIDE_ASCII_SYMBOL_TILDE) || 259 | target.is_match(WIDE_ASCII_SYMBOL_SPACE) 260 | } 261 | 262 | /// 数字かどうかを判定します。 263 | /// 半角・全角は区別しません。 264 | /// 265 | /// # Examples 266 | /// 267 | /// ``` 268 | /// use kanaria::utils::AsciiUtils; 269 | /// 270 | /// assert_eq!(AsciiUtils::is_number('1'), true); 271 | /// assert_eq!(AsciiUtils::is_number('1'), true); 272 | /// 273 | /// assert_eq!(AsciiUtils::is_number('A'), false); 274 | /// assert_eq!(AsciiUtils::is_number('A'), false); 275 | /// ``` 276 | #[inline] 277 | pub fn is_number(target: T) -> bool where T: UCSChar { 278 | AsciiUtils::is_narrow_number(target) || AsciiUtils::is_wide_number(target) 279 | } 280 | 281 | /// 半角数字かどうかを判定します。 282 | /// 283 | /// # Examples 284 | /// 285 | /// ``` 286 | /// use kanaria::utils::AsciiUtils; 287 | /// 288 | /// assert_eq!(AsciiUtils::is_narrow_number('1'), true); 289 | /// 290 | /// assert_eq!(AsciiUtils::is_narrow_number('1'), false); 291 | /// assert_eq!(AsciiUtils::is_narrow_number('A'), false); 292 | /// assert_eq!(AsciiUtils::is_narrow_number('A'), false); 293 | /// ``` 294 | #[inline] 295 | pub fn is_narrow_number(target: T) -> bool where T: UCSChar { 296 | target.is_in_range(NARROW_ASCII_NUMBER_0, NARROW_ASCII_NUMBER_9) 297 | } 298 | 299 | /// 全角数字かどうかを判定します。 300 | /// 301 | /// # Examples 302 | /// 303 | /// ``` 304 | /// use kanaria::utils::AsciiUtils; 305 | /// 306 | /// assert_eq!(AsciiUtils::is_wide_number('1'), true); 307 | /// 308 | /// assert_eq!(AsciiUtils::is_wide_number('1'), false); 309 | /// assert_eq!(AsciiUtils::is_wide_number('A'), false); 310 | /// assert_eq!(AsciiUtils::is_wide_number('A'), false); 311 | /// ``` 312 | #[inline] 313 | pub fn is_wide_number(target: T) -> bool where T: UCSChar { 314 | target.is_in_range(WIDE_ASCII_NUMBER_0, WIDE_ASCII_NUMBER_9) 315 | } 316 | 317 | /// 小文字を大文字に変換します。 318 | /// 半角・全角は区別しません。 319 | /// 320 | /// # Examples 321 | /// 322 | /// ``` 323 | /// use kanaria::utils::AsciiUtils; 324 | /// 325 | /// let ret = AsciiUtils::convert_to_upper_case('a'); 326 | /// assert_eq!(ret, 'A'); 327 | /// ``` 328 | #[inline] 329 | pub fn convert_to_upper_case(target_char: T) -> T where T: UCSChar { 330 | if AsciiUtils::is_lower_case(target_char) { 331 | target_char.subtraction(UNICODE_OFFSET_ALPHABET_UPPER_LOWER) 332 | } else { 333 | target_char 334 | } 335 | } 336 | 337 | /// 大文字を小文字に変換します。 338 | /// 半角・全角は区別しません。 339 | /// 340 | /// # Examples 341 | /// 342 | /// ``` 343 | /// use kanaria::utils::AsciiUtils; 344 | /// 345 | /// let ret = AsciiUtils::convert_to_lower_case('A'); 346 | /// assert_eq!(ret, 'a'); 347 | /// ``` 348 | #[inline] 349 | pub fn convert_to_lower_case(target_char: T) -> T where T: UCSChar { 350 | if AsciiUtils::is_upper_case(target_char) { 351 | target_char.addition(UNICODE_OFFSET_ALPHABET_UPPER_LOWER) 352 | } else { 353 | target_char 354 | } 355 | } 356 | } -------------------------------------------------------------------------------- /kanaria_core/src/utils/chars.rs: -------------------------------------------------------------------------------- 1 | use crate::UCSChar; 2 | use crate::utils::{AsciiUtils, KanaUtils}; 3 | 4 | pub struct CharsUtils; 5 | 6 | impl CharsUtils { 7 | /// 半角文字かどうかを判定します。 8 | /// 9 | /// # Examples 10 | /// 11 | /// ``` 12 | /// use kanaria::utils::CharsUtils; 13 | /// 14 | /// assert_eq!(CharsUtils::is_narrow('a'), true); 15 | /// assert_eq!(CharsUtils::is_narrow('A'), true); 16 | /// assert_eq!(CharsUtils::is_narrow('@'), true); 17 | /// assert_eq!(CharsUtils::is_narrow('0'), true); 18 | /// assert_eq!(CharsUtils::is_narrow('ア'), true); 19 | /// assert_eq!(CharsUtils::is_narrow('ー'), true); 20 | /// 21 | /// assert_eq!(CharsUtils::is_narrow('a'), false); 22 | /// assert_eq!(CharsUtils::is_narrow('A'), false); 23 | /// assert_eq!(CharsUtils::is_narrow('@'), false); 24 | /// assert_eq!(CharsUtils::is_narrow('0'), false); 25 | /// assert_eq!(CharsUtils::is_narrow('ア'), false); 26 | /// assert_eq!(CharsUtils::is_narrow('ー'), false); 27 | /// ``` 28 | #[inline] 29 | pub fn is_narrow(target: T) -> bool where T: UCSChar { 30 | AsciiUtils::is_narrow_ascii(target) || 31 | KanaUtils::is_narrow_katakana(target) || 32 | KanaUtils::is_narrow_jis_symbol(target) 33 | } 34 | 35 | /// 全角文字かどうかを判定します。 36 | /// 37 | /// # Examples 38 | /// 39 | /// ``` 40 | /// use kanaria::utils::CharsUtils; 41 | /// 42 | /// assert_eq!(CharsUtils::is_wide('a'), true); 43 | /// assert_eq!(CharsUtils::is_wide('A'), true); 44 | /// assert_eq!(CharsUtils::is_wide('@'), true); 45 | /// assert_eq!(CharsUtils::is_wide('0'), true); 46 | /// assert_eq!(CharsUtils::is_wide('ア'), true); 47 | /// assert_eq!(CharsUtils::is_wide('ー'), true); 48 | /// 49 | /// assert_eq!(CharsUtils::is_wide('a'), false); 50 | /// assert_eq!(CharsUtils::is_wide('A'), false); 51 | /// assert_eq!(CharsUtils::is_wide('@'), false); 52 | /// assert_eq!(CharsUtils::is_wide('0'), false); 53 | /// assert_eq!(CharsUtils::is_wide('ア'), false); 54 | /// assert_eq!(CharsUtils::is_wide('ー'), false); 55 | /// 56 | /// ``` 57 | #[inline] 58 | pub fn is_wide(target: T) -> bool where T: UCSChar { 59 | AsciiUtils::is_wide_ascii(target) || 60 | KanaUtils::is_wide_katakana(target) || 61 | KanaUtils::is_wide_jis_symbol(target) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /kanaria_core/src/utils/ext.rs: -------------------------------------------------------------------------------- 1 | use crate::UCSChar; 2 | 3 | pub trait CharExtend { 4 | fn to_char_vec(&self) -> Vec; 5 | fn to_u16_vec(&self) -> Vec; 6 | fn to_u32_vec(&self) -> Vec; 7 | } 8 | 9 | impl CharExtend for str { 10 | fn to_char_vec(&self) -> Vec { 11 | self.chars().map(|c| c).collect() 12 | } 13 | 14 | fn to_u16_vec(&self) -> Vec { 15 | self.encode_utf16().map(|scalar| u16::from_scalar(scalar )).collect() 16 | } 17 | 18 | fn to_u32_vec(&self) -> Vec { 19 | self.chars().map(|c| c as u32).collect() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kanaria_core/src/utils/kana.rs: -------------------------------------------------------------------------------- 1 | use crate::constants::*; 2 | use crate::UCSChar; 3 | 4 | /// かな<->カナ変換で使用します。 5 | /// この数値を加減算することでそれぞれを相互変換します。 6 | const UNICODE_OFFSET_HIRAGANA_ZENKAKU_KATAKANA: u32 = 0x0060; 7 | 8 | pub struct KanaUtils; 9 | 10 | impl KanaUtils { 11 | /// 対象がひらがなかどうかを判定します。 12 | /// 13 | /// # Examples 14 | /// 15 | /// ``` 16 | /// use kanaria::utils::KanaUtils; 17 | /// use kanaria::UCSChar; 18 | /// 19 | /// let true_case = KanaUtils::is_hiragana('あ'); 20 | /// assert_eq!(true_case, true); 21 | /// 22 | /// let false_case = KanaUtils::is_hiragana('ア'); 23 | /// assert_eq!(false_case, false); 24 | /// ``` 25 | #[inline] 26 | pub fn is_hiragana(target: T) -> bool where T: UCSChar { 27 | target.is_in_range(WIDE_KANA_HIRAGANA_SMALL_A, WIDE_KANA_HIRAGANA_SMALL_KE) || 28 | target.is_in_range(WIDE_KANA_HIRAGANA_ITERATION_MARK, WIDE_KANA_HIRAGANA_DIGRAPH_YORI) 29 | } 30 | 31 | /// 対象がカタカナかどうかを判定します。半角・全角は区別しません。 32 | /// 33 | /// # Examples 34 | /// 35 | /// ``` 36 | /// use kanaria::utils::KanaUtils; 37 | /// use kanaria::UCSChar; 38 | /// 39 | /// let true_case1 = KanaUtils::is_katakana('ア'); 40 | /// assert_eq!(true_case1, true); 41 | /// let true_case2 = KanaUtils::is_katakana('ア'); 42 | /// assert_eq!(true_case2, true); 43 | /// 44 | /// let false_case = KanaUtils::is_katakana('あ'); 45 | /// assert_eq!(false_case, false); 46 | /// ``` 47 | #[inline] 48 | pub fn is_katakana(target: T) -> bool where T: UCSChar { 49 | KanaUtils::is_narrow_katakana(target) || KanaUtils::is_wide_katakana(target) 50 | } 51 | 52 | /// 対象が半角カタカナかどうかを判定します。 53 | /// 54 | /// # Examples 55 | /// 56 | /// ``` 57 | /// use kanaria::utils::KanaUtils; 58 | /// use kanaria::UCSChar; 59 | /// 60 | /// let true_case = KanaUtils::is_narrow_katakana('ア'); 61 | /// assert_eq!(true_case, true); 62 | /// 63 | /// let false_case = KanaUtils::is_narrow_katakana('ア'); 64 | /// assert_eq!(false_case, false); 65 | /// ``` 66 | #[inline] 67 | pub fn is_narrow_katakana(target: T) -> bool where T: UCSChar { 68 | target.is_in_range(NARROW_KANA_KATAKANA_WO, NARROW_KANA_KATAKANA_SMALL_TU) || 69 | target.is_in_range(NARROW_KANA_KATAKANA_A, NARROW_KANA_KATAKANA_N) 70 | } 71 | 72 | /// 対象が全角カタカナかどうかを判定します。 73 | /// 74 | /// # Examples 75 | /// 76 | /// ``` 77 | /// use kanaria::utils::KanaUtils; 78 | /// use kanaria::UCSChar; 79 | /// 80 | /// let true_case = KanaUtils::is_wide_katakana('ア'); 81 | /// assert_eq!(true_case, true); 82 | /// 83 | /// let false_case = KanaUtils::is_wide_katakana('ア'); 84 | /// assert_eq!(false_case, false); 85 | /// ``` 86 | #[inline] 87 | pub fn is_wide_katakana(target: T) -> bool where T: UCSChar { 88 | target.is_in_range(WIDE_KANA_KATAKANA_SMALL_A, WIDE_KANA_KATAKANA_VO) || 89 | target.is_in_range(WIDE_KANA_KATAKANA_ITERATION_MARK, WIDE_KANA_KATAKANA_DIGRAPH_YORI) 90 | } 91 | 92 | /// 対象が半角記号かどうかを判定します。ASCIIコード内の記号はtrueになりません。 93 | /// 94 | /// # Examples 95 | /// 96 | /// ``` 97 | /// use kanaria::utils::KanaUtils; 98 | /// use kanaria::UCSChar; 99 | /// 100 | /// let true_case1 = KanaUtils::is_jis_symbol('ー'); 101 | /// assert_eq!(true_case1, true); 102 | /// let true_case2 = KanaUtils::is_jis_symbol('ー'); 103 | /// assert_eq!(true_case2, true); 104 | /// 105 | /// let false_case = KanaUtils::is_jis_symbol('あ'); 106 | /// assert_eq!(false_case, false); 107 | /// ``` 108 | #[inline] 109 | pub fn is_jis_symbol(target: T) -> bool { 110 | KanaUtils::is_narrow_jis_symbol(target) || KanaUtils::is_wide_jis_symbol(target) 111 | } 112 | 113 | /// 対象が半角記号かどうかを判定します。ASCIIコード内の記号はtrueになりません。 114 | /// 115 | /// # Examples 116 | /// 117 | /// ``` 118 | /// use kanaria::utils::KanaUtils; 119 | /// use kanaria::UCSChar; 120 | /// 121 | /// let true_case = KanaUtils::is_narrow_jis_symbol('ー'); 122 | /// assert_eq!(true_case, true); 123 | /// 124 | /// let false_case = KanaUtils::is_narrow_jis_symbol('ー'); 125 | /// assert_eq!(false_case, false); 126 | /// ``` 127 | #[inline] 128 | pub fn is_narrow_jis_symbol(target: T) -> bool where T: UCSChar { 129 | target.is_in_range(NARROW_JIS_SYMBOL_KATAKANA_VOICED_SOUND_MARK, NARROW_JIS_SYMBOL_KATAKANA_SEMI_VOICED_SOUND_MARK) || 130 | target.is_contains(&[NARROW_JIS_SYMBOL_KATAKANA_MIDDLE_DOT, NARROW_JIS_SYMBOL_PROLONGED_SOUND_MARK]) 131 | } 132 | 133 | /// 対象が全角記号かどうかを判定します。ASCIIコード内の記号はtrueになりません。 134 | /// 135 | /// # Examples 136 | /// 137 | /// ``` 138 | /// use kanaria::utils::KanaUtils; 139 | /// use kanaria::UCSChar; 140 | /// 141 | /// let true_case = KanaUtils::is_wide_jis_symbol('ー'); 142 | /// assert_eq!(true_case, true); 143 | /// 144 | /// let false_case = KanaUtils::is_wide_jis_symbol('ー'); 145 | /// assert_eq!(false_case, false); 146 | /// ``` 147 | #[inline] 148 | pub fn is_wide_jis_symbol(target: T) -> bool where T: UCSChar { 149 | target.is_in_range(WIDE_JIS_SYMBOL_KATAKANA_SEMI_VOICED_SOUND_MARK, WIDE_JIS_SYMBOL_KATAKANA_SEMI_VOICED_SOUND_MARK) || 150 | target.is_in_range(WIDE_KANA_HIRAGANA_ITERATION_MARK, WIDE_KANA_HIRAGANA_VOICED_ITERATION_MARK) || 151 | target.is_in_range(WIDE_KANA_KATAKANA_ITERATION_MARK, WIDE_KANA_KATAKANA_VOICED_ITERATION_MARK) || 152 | target.is_contains(&[ 153 | WIDE_JIS_SYMBOL_MIDDLE_DOT, 154 | WIDE_JIS_SYMBOL_MIDDLE_DOT, 155 | WIDE_JIS_SYMBOL_KATAKANA_MIDDLE_DOT, 156 | WIDE_JIS_SYMBOL_PROLONGED_SOUND_MARK, 157 | WIDE_KANA_HIRAGANA_DIGRAPH_YORI, 158 | WIDE_KANA_KATAKANA_DIGRAPH_YORI, 159 | ]) 160 | } 161 | 162 | /// ひらがなに変換可能な全角カタカナかどうかを判定します。 163 | /// 164 | /// # Examples 165 | /// 166 | /// ``` 167 | /// use kanaria::utils::KanaUtils; 168 | /// use kanaria::UCSChar; 169 | /// 170 | /// let true_case = KanaUtils::is_can_convert_hiragana('ア'); 171 | /// assert_eq!(true_case, true); 172 | /// ``` 173 | #[inline] 174 | pub fn is_can_convert_hiragana(target: T) -> bool where T: UCSChar { 175 | target.is_in_range(WIDE_KANA_KATAKANA_SMALL_A, WIDE_KANA_KATAKANA_SMALL_KE) || 176 | target.is_in_range(WIDE_KANA_KATAKANA_ITERATION_MARK, WIDE_KANA_KATAKANA_DIGRAPH_YORI) 177 | } 178 | 179 | /// 全角カタカナをひらがなに変換します。 180 | /// 181 | /// # Examples 182 | /// 183 | /// ``` 184 | /// use kanaria::utils::KanaUtils; 185 | /// use kanaria::UCSChar; 186 | /// 187 | /// let ret = KanaUtils::convert_to_hiragana('ア'); 188 | /// assert_eq!(ret, 'あ'); 189 | /// ``` 190 | #[inline] 191 | pub fn convert_to_hiragana(target_char: T) -> T where T: UCSChar { 192 | if KanaUtils::is_can_convert_hiragana(target_char) { 193 | target_char.subtraction(UNICODE_OFFSET_HIRAGANA_ZENKAKU_KATAKANA) 194 | } else { 195 | target_char 196 | } 197 | } 198 | 199 | /// ひらがなを全角カタカナに変換します。 200 | /// 201 | /// # Examples 202 | /// 203 | /// ``` 204 | /// use kanaria::utils::KanaUtils; 205 | /// use kanaria::UCSChar; 206 | /// 207 | /// let ret = KanaUtils::convert_to_katakana('あ'); 208 | /// assert_eq!(ret, 'ア'); 209 | /// ``` 210 | #[inline] 211 | pub fn convert_to_katakana(target_char: T) -> T where T: UCSChar { 212 | if KanaUtils::is_hiragana(target_char) { 213 | target_char.addition(UNICODE_OFFSET_HIRAGANA_ZENKAKU_KATAKANA) 214 | } else { 215 | target_char 216 | } 217 | } 218 | } -------------------------------------------------------------------------------- /kanaria_core/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::chars::CharsUtils; 2 | pub use self::ascii::AsciiUtils; 3 | pub use self::kana::KanaUtils; 4 | pub use self::width::ConvertTarget; 5 | pub use self::width::WidthUtils; 6 | pub use crate::utils::ext::CharExtend; 7 | 8 | mod ext; 9 | mod chars; 10 | mod ascii; 11 | mod kana; 12 | mod width; 13 | -------------------------------------------------------------------------------- /kanaria_core/tests/example_sentence.rs: -------------------------------------------------------------------------------- 1 | extern crate kanaria; 2 | 3 | use kanaria::string::{UCSStr}; 4 | use kanaria::utils::{ConvertTarget}; 5 | 6 | #[test] 7 | fn example_sentence_1() { 8 | let hiragana = "ちたたぷ とてとて"; 9 | let katakana = "チタタプ トテトテ"; 10 | 11 | assert_eq!(UCSStr::from_str(katakana).hiragana().to_string(), hiragana.to_string()); 12 | assert_eq!(UCSStr::from_str(hiragana).katakana().to_string(), katakana.to_string()); 13 | } 14 | 15 | #[test] 16 | fn example_sentence_2() { 17 | let hiragana = "吾輩は😺猫である😺"; 18 | let katakana = "吾輩ハ😺猫デアル😺"; 19 | 20 | assert_eq!(UCSStr::from_str(katakana).hiragana().to_string(), hiragana.to_string()); 21 | assert_eq!(UCSStr::from_str(hiragana).katakana().to_string(), katakana.to_string()); 22 | } 23 | 24 | #[test] 25 | fn example_sentence_3() { 26 | let hankaku = "チタタプ トテトテFoooo!!!11!"; 27 | let zenkaku = "チタタプ トテトテFoooo!!!11!"; 28 | 29 | assert_eq!(UCSStr::from_str(zenkaku).narrow(ConvertTarget::ALL).to_string(), hankaku.to_string()); 30 | assert_eq!(UCSStr::from_str(hankaku).wide(ConvertTarget::ALL).to_string(), zenkaku.to_string()); 31 | } 32 | 33 | #[test] 34 | fn example_sentence_4() { 35 | let hankaku = "吾輩ハ😺猫デアル😺"; 36 | let zenkaku = "吾輩ハ😺猫デアル😺"; 37 | 38 | assert_eq!(UCSStr::from_str(zenkaku).narrow(ConvertTarget::ALL).to_string(), hankaku.to_string()); 39 | assert_eq!(UCSStr::from_str(hankaku).wide(ConvertTarget::ALL).to_string(), zenkaku.to_string()); 40 | } 41 | 42 | #[test] 43 | fn example_sentence_5() { 44 | let source = "吾輩は😺猫である😺"; 45 | let expect = "吾輩ハ😺猫デアル😺"; 46 | let expect2 = "吾輩ハ😺猫デアル😺"; 47 | 48 | assert_eq!(expect.to_string(), UCSStr::from_str(source).katakana().narrow(ConvertTarget::ALL).to_string()); 49 | assert_eq!(expect2.to_string(), UCSStr::from_str(source).katakana().narrow(ConvertTarget::NUMBER | ConvertTarget::SYMBOL | ConvertTarget::ALPHABET).to_string()); 50 | } 51 | -------------------------------------------------------------------------------- /kanaria_core/tests/narrow_wide.rs: -------------------------------------------------------------------------------- 1 | extern crate kanaria; 2 | 3 | use kanaria::UCSChar; 4 | use kanaria::utils::WidthUtils; 5 | 6 | #[test] 7 | fn convert_to_wide() { 8 | WIDE_NARROW_LIST.iter().for_each(|item| { 9 | let mut iter = item.narrow.chars(); 10 | let first = if let Some(c) = iter.next() { 11 | c 12 | } else { 13 | panic!() 14 | }; 15 | 16 | let second = if let Some(c) = iter.next() { 17 | c 18 | } else { 19 | char::NULL 20 | }; 21 | 22 | let (result, _) = WidthUtils::convert_to_wide(first, second); 23 | assert_eq!(result.to_string().as_str(), item.wide) 24 | }) 25 | } 26 | 27 | #[test] 28 | fn convert_to_narrow() { 29 | WIDE_NARROW_LIST.iter().for_each(|item| { 30 | let (first, second) = WidthUtils::convert_to_narrow(item.wide.chars().next().unwrap()); 31 | 32 | let mut result = first.to_string(); 33 | if second != char::NULL { 34 | result.push(second); 35 | } 36 | 37 | assert_eq!(result.as_str(), item.narrow) 38 | }) 39 | } 40 | 41 | struct Pair<'a> { 42 | pub wide: &'a str, 43 | pub narrow: &'a str, 44 | } 45 | 46 | impl<'a> Pair<'a> { 47 | pub const fn create(wide: &'a str, narrow: &'a str) -> Self { 48 | Self { 49 | wide, 50 | narrow, 51 | } 52 | } 53 | } 54 | 55 | static WIDE_NARROW_LIST: &[Pair] = &[ 56 | Pair::create("←", "←"), 57 | Pair::create("↑", "↑"), 58 | Pair::create("→", "→"), 59 | Pair::create("↓", "↓"), 60 | Pair::create("│", "│"), 61 | Pair::create("■", "■"), 62 | Pair::create("○", "○"), 63 | Pair::create("⦅", "⦅"), 64 | Pair::create("⦆", "⦆"), 65 | Pair::create(" ", " "), 66 | Pair::create("、", "、"), 67 | Pair::create("。", "。"), 68 | Pair::create("「", "「"), 69 | Pair::create("」", "」"), 70 | Pair::create("゙", "゙"), 71 | Pair::create("゚", "゚"), 72 | Pair::create("ァ", "ァ"), 73 | Pair::create("ア", "ア"), 74 | Pair::create("ィ", "ィ"), 75 | Pair::create("イ", "イ"), 76 | Pair::create("ゥ", "ゥ"), 77 | Pair::create("ウ", "ウ"), 78 | Pair::create("ェ", "ェ"), 79 | Pair::create("エ", "エ"), 80 | Pair::create("ォ", "ォ"), 81 | Pair::create("オ", "オ"), 82 | Pair::create("カ", "カ"), 83 | Pair::create("キ", "キ"), 84 | Pair::create("ク", "ク"), 85 | Pair::create("ケ", "ケ"), 86 | Pair::create("コ", "コ"), 87 | Pair::create("サ", "サ"), 88 | Pair::create("シ", "シ"), 89 | Pair::create("ス", "ス"), 90 | Pair::create("セ", "セ"), 91 | Pair::create("ソ", "ソ"), 92 | Pair::create("タ", "タ"), 93 | Pair::create("チ", "チ"), 94 | Pair::create("ッ", "ッ"), 95 | Pair::create("ツ", "ツ"), 96 | Pair::create("テ", "テ"), 97 | Pair::create("ト", "ト"), 98 | Pair::create("ナ", "ナ"), 99 | Pair::create("ニ", "ニ"), 100 | Pair::create("ヌ", "ヌ"), 101 | Pair::create("ネ", "ネ"), 102 | Pair::create("ノ", "ノ"), 103 | Pair::create("ハ", "ハ"), 104 | Pair::create("ヒ", "ヒ"), 105 | Pair::create("フ", "フ"), 106 | Pair::create("ヘ", "ヘ"), 107 | Pair::create("ホ", "ホ"), 108 | Pair::create("マ", "マ"), 109 | Pair::create("ミ", "ミ"), 110 | Pair::create("ム", "ム"), 111 | Pair::create("メ", "メ"), 112 | Pair::create("モ", "モ"), 113 | Pair::create("ャ", "ャ"), 114 | Pair::create("ヤ", "ヤ"), 115 | Pair::create("ュ", "ュ"), 116 | Pair::create("ユ", "ユ"), 117 | Pair::create("ョ", "ョ"), 118 | Pair::create("ヨ", "ヨ"), 119 | Pair::create("ラ", "ラ"), 120 | Pair::create("リ", "リ"), 121 | Pair::create("ル", "ル"), 122 | Pair::create("レ", "レ"), 123 | Pair::create("ロ", "ロ"), 124 | Pair::create("ワ", "ワ"), 125 | Pair::create("ヲ", "ヲ"), 126 | Pair::create("ン", "ン"), 127 | Pair::create("・", "・"), 128 | Pair::create("ー", "ー"), 129 | Pair::create("!", "!"), 130 | Pair::create(""", "\""), 131 | Pair::create("#", "#"), 132 | Pair::create("$", "$"), 133 | Pair::create("%", "%"), 134 | Pair::create("&", "&"), 135 | Pair::create("'", "'"), 136 | Pair::create("(", "("), 137 | Pair::create(")", ")"), 138 | Pair::create("*", "*"), 139 | Pair::create("+", "+"), 140 | Pair::create(",", ","), 141 | Pair::create("-", "-"), 142 | Pair::create(".", "."), 143 | Pair::create("/", "/"), 144 | Pair::create("0", "0"), 145 | Pair::create("1", "1"), 146 | Pair::create("2", "2"), 147 | Pair::create("3", "3"), 148 | Pair::create("4", "4"), 149 | Pair::create("5", "5"), 150 | Pair::create("6", "6"), 151 | Pair::create("7", "7"), 152 | Pair::create("8", "8"), 153 | Pair::create("9", "9"), 154 | Pair::create(":", ":"), 155 | Pair::create(";", ";"), 156 | Pair::create("<", "<"), 157 | Pair::create("=", "="), 158 | Pair::create(">", ">"), 159 | Pair::create("?", "?"), 160 | Pair::create("@", "@"), 161 | Pair::create("A", "A"), 162 | Pair::create("B", "B"), 163 | Pair::create("C", "C"), 164 | Pair::create("D", "D"), 165 | Pair::create("E", "E"), 166 | Pair::create("F", "F"), 167 | Pair::create("G", "G"), 168 | Pair::create("H", "H"), 169 | Pair::create("I", "I"), 170 | Pair::create("J", "J"), 171 | Pair::create("K", "K"), 172 | Pair::create("L", "L"), 173 | Pair::create("M", "M"), 174 | Pair::create("N", "N"), 175 | Pair::create("O", "O"), 176 | Pair::create("P", "P"), 177 | Pair::create("Q", "Q"), 178 | Pair::create("R", "R"), 179 | Pair::create("S", "S"), 180 | Pair::create("T", "T"), 181 | Pair::create("U", "U"), 182 | Pair::create("V", "V"), 183 | Pair::create("W", "W"), 184 | Pair::create("X", "X"), 185 | Pair::create("Y", "Y"), 186 | Pair::create("Z", "Z"), 187 | Pair::create("[", "["), 188 | Pair::create("\", "\\"), 189 | Pair::create("]", "]"), 190 | Pair::create("^", "^"), 191 | Pair::create("_", "_"), 192 | Pair::create("`", "`"), 193 | Pair::create("a", "a"), 194 | Pair::create("b", "b"), 195 | Pair::create("c", "c"), 196 | Pair::create("d", "d"), 197 | Pair::create("e", "e"), 198 | Pair::create("f", "f"), 199 | Pair::create("g", "g"), 200 | Pair::create("h", "h"), 201 | Pair::create("i", "i"), 202 | Pair::create("j", "j"), 203 | Pair::create("k", "k"), 204 | Pair::create("l", "l"), 205 | Pair::create("m", "m"), 206 | Pair::create("n", "n"), 207 | Pair::create("o", "o"), 208 | Pair::create("p", "p"), 209 | Pair::create("q", "q"), 210 | Pair::create("r", "r"), 211 | Pair::create("s", "s"), 212 | Pair::create("t", "t"), 213 | Pair::create("u", "u"), 214 | Pair::create("v", "v"), 215 | Pair::create("w", "w"), 216 | Pair::create("x", "x"), 217 | Pair::create("y", "y"), 218 | Pair::create("z", "z"), 219 | Pair::create("{", "{"), 220 | Pair::create("|", "|"), 221 | Pair::create("}", "}"), 222 | Pair::create("~", "~"), 223 | Pair::create("¢", "¢"), 224 | Pair::create("£", "£"), 225 | Pair::create("¬", "¬"), 226 | Pair::create(" ̄", "¯"), 227 | Pair::create("¦", "¦"), 228 | Pair::create("¥", "¥"), 229 | Pair::create("₩", "₩"), 230 | Pair::create("ガ", "ガ"), 231 | Pair::create("ギ", "ギ"), 232 | Pair::create("グ", "グ"), 233 | Pair::create("ゲ", "ゲ"), 234 | Pair::create("ゴ", "ゴ"), 235 | Pair::create("ザ", "ザ"), 236 | Pair::create("ジ", "ジ"), 237 | Pair::create("ズ", "ズ"), 238 | Pair::create("ゼ", "ゼ"), 239 | Pair::create("ゾ", "ゾ"), 240 | Pair::create("ダ", "ダ"), 241 | Pair::create("ヂ", "ヂ"), 242 | Pair::create("ヅ", "ヅ"), 243 | Pair::create("デ", "デ"), 244 | Pair::create("ド", "ド"), 245 | Pair::create("バ", "バ"), 246 | Pair::create("パ", "パ"), 247 | Pair::create("ビ", "ビ"), 248 | Pair::create("ピ", "ピ"), 249 | Pair::create("ブ", "ブ"), 250 | Pair::create("プ", "プ"), 251 | Pair::create("ベ", "ベ"), 252 | Pair::create("ペ", "ペ"), 253 | Pair::create("ボ", "ボ"), 254 | Pair::create("ポ", "ポ"), 255 | Pair::create("ヴ", "ヴ"), 256 | Pair::create("ヷ", "ヷ"), 257 | Pair::create("ヺ", "ヺ"), 258 | ]; 259 | -------------------------------------------------------------------------------- /kanaria_dotnet/.gitignore: -------------------------------------------------------------------------------- 1 | kanaria.dll 2 | FodyWeavers.xsd 3 | 4 | # Created by https://www.gitignore.io/api/rider 5 | # Edit at https://www.gitignore.io/?templates=rider 6 | 7 | ### Rider ### 8 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 9 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 10 | 11 | # User-specific stuff 12 | .idea/**/workspace.xml 13 | .idea/**/tasks.xml 14 | .idea/**/usage.statistics.xml 15 | .idea/**/dictionaries 16 | .idea/**/shelf 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/modules.xml 39 | # .idea/*.iml 40 | # .idea/modules 41 | 42 | # CMake 43 | cmake-build-*/ 44 | 45 | # Mongo Explorer plugin 46 | .idea/**/mongoSettings.xml 47 | 48 | # File-based project format 49 | *.iws 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Cursive Clojure plugin 61 | .idea/replstate.xml 62 | 63 | # Crashlytics plugin (for Android Studio and IntelliJ) 64 | com_crashlytics_export_strings.xml 65 | crashlytics.properties 66 | crashlytics-build.properties 67 | fabric.properties 68 | 69 | # Editor-based Rest Client 70 | .idea/httpRequests 71 | 72 | # Android studio 3.1+ serialized cache file 73 | .idea/caches/build_file_checksums.ser 74 | 75 | # End of https://www.gitignore.io/api/rider 76 | 77 | 78 | 79 | ## Ignore Visual Studio temporary files, build results, and 80 | ## files generated by popular Visual Studio add-ons. 81 | ## 82 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 83 | 84 | # User-specific files 85 | *.suo 86 | *.user 87 | *.userosscache 88 | *.sln.docstates 89 | 90 | # User-specific files (MonoDevelop/Xamarin Studio) 91 | *.userprefs 92 | 93 | # Build results 94 | [Dd]ebug/ 95 | [Dd]ebugPublic/ 96 | [Rr]elease/ 97 | [Rr]eleases/ 98 | x64/ 99 | x86/ 100 | bld/ 101 | [Bb]in/ 102 | [Oo]bj/ 103 | [Ll]og/ 104 | 105 | # Visual Studio 2015/2017 cache/options directory 106 | .vs/ 107 | # Uncomment if you have tasks that create the project's static files in wwwroot 108 | #wwwroot/ 109 | 110 | # Visual Studio 2017 auto generated files 111 | Generated\ Files/ 112 | 113 | # MSTest test Results 114 | [Tt]est[Rr]esult*/ 115 | [Bb]uild[Ll]og.* 116 | 117 | # NUNIT 118 | *.VisualState.xml 119 | TestResult.xml 120 | 121 | # Build Results of an ATL Project 122 | [Dd]ebugPS/ 123 | [Rr]eleasePS/ 124 | dlldata.c 125 | 126 | # Benchmark Results 127 | BenchmarkDotNet.Artifacts/ 128 | 129 | # .NET Core 130 | project.lock.json 131 | project.fragment.lock.json 132 | artifacts/ 133 | **/Properties/launchSettings.json 134 | 135 | # StyleCop 136 | StyleCopReport.xml 137 | 138 | # Files built by Visual Studio 139 | *_i.c 140 | *_p.c 141 | *_i.h 142 | *.ilk 143 | *.meta 144 | *.obj 145 | *.iobj 146 | *.pch 147 | *.pdb 148 | *.ipdb 149 | *.pgc 150 | *.pgd 151 | *.rsp 152 | *.sbr 153 | *.tlb 154 | *.tli 155 | *.tlh 156 | *.tmp 157 | *.tmp_proj 158 | *.log 159 | *.vspscc 160 | *.vssscc 161 | .builds 162 | *.pidb 163 | *.svclog 164 | *.scc 165 | 166 | # Chutzpah Test files 167 | _Chutzpah* 168 | 169 | # Visual C++ cache files 170 | ipch/ 171 | *.aps 172 | *.ncb 173 | *.opendb 174 | *.opensdf 175 | *.sdf 176 | *.cachefile 177 | *.VC.db 178 | *.VC.VC.opendb 179 | 180 | # Visual Studio profiler 181 | *.psess 182 | *.vsp 183 | *.vspx 184 | *.sap 185 | 186 | # Visual Studio Trace Files 187 | *.e2e 188 | 189 | # TFS 2012 Local Workspace 190 | $tf/ 191 | 192 | # Guidance Automation Toolkit 193 | *.gpState 194 | 195 | # ReSharper is a .NET coding add-in 196 | _ReSharper*/ 197 | *.[Rr]e[Ss]harper 198 | *.DotSettings.user 199 | 200 | # JustCode is a .NET coding add-in 201 | .JustCode 202 | 203 | # TeamCity is a build add-in 204 | _TeamCity* 205 | 206 | # DotCover is a Code Coverage Tool 207 | *.dotCover 208 | 209 | # AxoCover is a Code Coverage Tool 210 | .axoCover/* 211 | !.axoCover/settings.json 212 | 213 | # Visual Studio code coverage results 214 | *.coverage 215 | *.coveragexml 216 | 217 | # NCrunch 218 | _NCrunch_* 219 | .*crunch*.local.xml 220 | nCrunchTemp_* 221 | 222 | # MightyMoose 223 | *.mm.* 224 | AutoTest.Net/ 225 | 226 | # Web workbench (sass) 227 | .sass-cache/ 228 | 229 | # Installshield output folder 230 | [Ee]xpress/ 231 | 232 | # DocProject is a documentation generator add-in 233 | DocProject/buildhelp/ 234 | DocProject/Help/*.HxT 235 | DocProject/Help/*.HxC 236 | DocProject/Help/*.hhc 237 | DocProject/Help/*.hhk 238 | DocProject/Help/*.hhp 239 | DocProject/Help/Html2 240 | DocProject/Help/html 241 | 242 | # Click-Once directory 243 | publish/ 244 | 245 | # Publish Web Output 246 | *.[Pp]ublish.xml 247 | *.azurePubxml 248 | # Note: Comment the next line if you want to checkin your web deploy settings, 249 | # but database connection strings (with potential passwords) will be unencrypted 250 | *.pubxml 251 | *.publishproj 252 | 253 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 254 | # checkin your Azure Web App publish settings, but sensitive information contained 255 | # in these scripts will be unencrypted 256 | PublishScripts/ 257 | 258 | # NuGet Packages 259 | *.nupkg 260 | # The packages folder can be ignored because of Package Restore 261 | **/[Pp]ackages/* 262 | # except build/, which is used as an MSBuild target. 263 | !**/[Pp]ackages/build/ 264 | # Uncomment if necessary however generally it will be regenerated when needed 265 | #!**/[Pp]ackages/repositories.config 266 | # NuGet v3's project.json files produces more ignorable files 267 | *.nuget.props 268 | *.nuget.targets 269 | 270 | # Microsoft Azure Build Output 271 | csx/ 272 | *.build.csdef 273 | 274 | # Microsoft Azure Emulator 275 | ecf/ 276 | rcf/ 277 | 278 | # Windows Store app package directories and files 279 | AppPackages/ 280 | BundleArtifacts/ 281 | Package.StoreAssociation.xml 282 | _pkginfo.txt 283 | *.appx 284 | 285 | # Visual Studio cache files 286 | # files ending in .cache can be ignored 287 | *.[Cc]ache 288 | # but keep track of directories ending in .cache 289 | !*.[Cc]ache/ 290 | 291 | # Others 292 | ClientBin/ 293 | ~$* 294 | *~ 295 | *.dbmdl 296 | *.dbproj.schemaview 297 | *.jfm 298 | *.pfx 299 | *.publishsettings 300 | orleans.codegen.cs 301 | 302 | # Including strong name files can present a security risk 303 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 304 | #*.snk 305 | 306 | # Since there are multiple workflows, uncomment next line to ignore bower_components 307 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 308 | #bower_components/ 309 | 310 | # RIA/Silverlight projects 311 | Generated_Code/ 312 | 313 | # Backup & report files from converting an old project file 314 | # to a newer Visual Studio version. Backup files are not needed, 315 | # because we have git ;-) 316 | _UpgradeReport_Files/ 317 | Backup*/ 318 | UpgradeLog*.XML 319 | UpgradeLog*.htm 320 | ServiceFabricBackup/ 321 | *.rptproj.bak 322 | 323 | # SQL Server files 324 | *.mdf 325 | *.ldf 326 | *.ndf 327 | 328 | # Business Intelligence projects 329 | *.rdl.data 330 | *.bim.layout 331 | *.bim_*.settings 332 | *.rptproj.rsuser 333 | 334 | # Microsoft Fakes 335 | FakesAssemblies/ 336 | 337 | # GhostDoc plugin setting file 338 | *.GhostDoc.xml 339 | 340 | # Node.js Tools for Visual Studio 341 | .ntvs_analysis.dat 342 | node_modules/ 343 | 344 | # Visual Studio 6 build log 345 | *.plg 346 | 347 | # Visual Studio 6 workspace options file 348 | *.opt 349 | 350 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 351 | *.vbw 352 | 353 | # Visual Studio LightSwitch build output 354 | **/*.HTMLClient/GeneratedArtifacts 355 | **/*.DesktopClient/GeneratedArtifacts 356 | **/*.DesktopClient/ModelManifest.xml 357 | **/*.Server/GeneratedArtifacts 358 | **/*.Server/ModelManifest.xml 359 | _Pvt_Extensions 360 | 361 | # Paket dependency manager 362 | .paket/paket.exe 363 | paket-files/ 364 | 365 | # FAKE - F# Make 366 | .fake/ 367 | 368 | # JetBrains Rider 369 | .idea/ 370 | *.sln.iml 371 | 372 | # CodeRush 373 | .cr/ 374 | 375 | # Python Tools for Visual Studio (PTVS) 376 | __pycache__/ 377 | *.pyc 378 | 379 | # Cake - Uncomment if you are using it 380 | # tools/** 381 | # !tools/packages.config 382 | 383 | # Tabs Studio 384 | *.tss 385 | 386 | # Telerik's JustMock configuration file 387 | *.jmconfig 388 | 389 | # BizTalk build output 390 | *.btp.cs 391 | *.btm.cs 392 | *.odx.cs 393 | *.xsd.cs 394 | 395 | # OpenCover UI analysis results 396 | OpenCover/ 397 | 398 | # Azure Stream Analytics local run output 399 | ASALocalRun/ 400 | 401 | # MSBuild Binary and Structured Log 402 | *.binlog 403 | 404 | # NVidia Nsight GPU debugger configuration file 405 | *.nvuser 406 | 407 | # MFractors (Xamarin productivity tool) working folder 408 | .mfractor/ 409 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | kanaria 6 | 7 | 8 | kanaria 9 | 10 | 11 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/KanariaDotNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 8 5 | enable 6 | Kanaria 7 | net40 8 | 1.1.0 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/KanariaDotNet.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kanaria.Net 5 | Kanaria for .NET 6 | 7 | This library provides features such as hiragana, katakana, half-width and full-width mutual conversion and identification. 8 | Also, this library is a wrapper for the native library created by Rust. 9 | 10 | 11 | 0.2.0 12 | 13 | 14 | https://github.com/samunohito/kanaria 15 | MIT 16 | false 17 | 18 | sam_osamu 19 | samu no hito 20 | Copyright 2019 samu no hito 21 | 22 | katakana hiragana kana 23 | 24 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/costura32/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samunohito/kanaria/9c2a6237d5a523f372b50d956671251710d5f4ac/kanaria_dotnet/KanariaDotNet/costura32/.gitkeep -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/costura64/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samunohito/kanaria/9c2a6237d5a523f372b50d956671251710d5f4ac/kanaria_dotnet/KanariaDotNet/costura64/.gitkeep -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/src/ConvertTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Kanaria 4 | { 5 | [Flags] 6 | public enum ConvertTarget 7 | { 8 | /// 9 | /// 半角・全角の変換対象として数値を設定する際のビットフラグです。 10 | /// 11 | Number = 0b00000001, 12 | /// 13 | /// 半角・全角の変換対象としてアルファベットを設定する際のビットフラグです。 14 | /// 15 | Alphabet = 0b00000010, 16 | /// 17 | /// 半角・全角の変換対象として記号を設定する際のビットフラグです。 18 | /// 19 | Symbol = 0b00000100, 20 | /// 21 | /// 半角・全角の変換対象としてカタカナを設定する際のビットフラグです。 22 | /// 23 | Katakana = 0b00001000, 24 | /// 25 | /// 半角・全角の変換が可能なものはすべて変換します。 26 | /// 27 | All = (Number | Alphabet| Symbol| Katakana) 28 | } 29 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/src/UCSString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace Kanaria 8 | { 9 | public class UcsString 10 | { 11 | private readonly string _target; 12 | private readonly List _convertTypes; 13 | 14 | /// 15 | /// コンストラクタ 16 | /// 17 | /// 処理対象文字列 18 | private UcsString(string target) 19 | { 20 | _target = target; 21 | _convertTypes = new List(); 22 | } 23 | 24 | /// 25 | /// このクラスのインスタンスを作成します。 26 | /// 27 | /// 処理対象文字列 28 | /// インスタンス 29 | public static UcsString From(string target) 30 | { 31 | return new UcsString(target); 32 | } 33 | 34 | /// 35 | /// このクラスのインスタンスを作成します。 36 | /// 37 | /// 処理対象文字列 38 | /// インスタンス 39 | public static UcsString From(IEnumerable target) 40 | { 41 | return new UcsString(new string(target.ToArray())); 42 | } 43 | 44 | /// 45 | /// 文字列を大文字に変換するように設定します。 46 | /// 47 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 48 | public UcsString UpperCase() 49 | { 50 | _convertTypes.Add(new RequestParameter(RequestType.UpperCase)); 51 | return this; 52 | } 53 | 54 | /// 55 | /// 文字列を小文字に変換するように設定します。 56 | /// 57 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 58 | public UcsString LowerCase() 59 | { 60 | _convertTypes.Add(new RequestParameter(RequestType.LowerCase)); 61 | return this; 62 | } 63 | 64 | /// 65 | /// 文字列をひらがなに変換するように設定します。 66 | /// 67 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 68 | public UcsString Katakana() 69 | { 70 | _convertTypes.Add(new RequestParameter(RequestType.Katakana)); 71 | return this; 72 | } 73 | 74 | /// 75 | /// 文字列を全角カタカナに変換するように設定します。 76 | /// 77 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 78 | public UcsString Hiragana() 79 | { 80 | _convertTypes.Add(new RequestParameter(RequestType.Hiragana)); 81 | return this; 82 | } 83 | 84 | /// 85 | /// 文字列を全角に変換するように設定します。 86 | /// 87 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 88 | public UcsString Wide(ConvertTarget target = ConvertTarget.All) 89 | { 90 | _convertTypes.Add(new RequestParameter(RequestType.Wide, target)); 91 | return this; 92 | } 93 | 94 | /// 95 | /// 文字列を半角に変換するように設定します。 96 | /// 97 | /// このインスタンス。ToString()の呼び出しで変換処理を行います。 98 | public UcsString Narrow(ConvertTarget target = ConvertTarget.All) 99 | { 100 | _convertTypes.Add(new RequestParameter(RequestType.Narrow, target)); 101 | return this; 102 | } 103 | 104 | /// 105 | /// 文字列を変換し、stringとして返却します。 106 | /// このメソッドの呼出前にUpperCase()、LowerCase()、Hiragana()、Katakana()、Wide()、Narrow()等を呼び出し、 107 | /// 変換先の設定を行う必要があります。 108 | /// 109 | /// 変換後文字列 110 | public override string ToString() 111 | { 112 | var tmpBuffer = _target; 113 | 114 | _convertTypes.ForEach(param => 115 | { 116 | var type = param.Type; 117 | var target = param.ConvertTarget; 118 | 119 | // 半角文字の場合、濁音等で文字数が2文字に増えるケースもあるので2倍長さを確保しておく 120 | var resultBufferSize = (type == RequestType.Narrow) ? tmpBuffer.Length * 2 : tmpBuffer.Length; 121 | // 終端文字考慮で1つ分長くする。 122 | var sb = new StringBuilder(resultBufferSize + 1); 123 | 124 | switch (type) 125 | { 126 | case RequestType.UpperCase: 127 | ToUpperCase(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity); 128 | break; 129 | case RequestType.LowerCase: 130 | ToLowerCase(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity); 131 | break; 132 | case RequestType.Hiragana: 133 | ToHiragana(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity); 134 | break; 135 | case RequestType.Katakana: 136 | ToKatakana(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity); 137 | break; 138 | case RequestType.Wide: 139 | ToWide(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity, (uint) target); 140 | break; 141 | case RequestType.Narrow: 142 | ToNarrow(tmpBuffer, (uint) tmpBuffer.Length, sb, (uint) sb.Capacity, (uint) target); 143 | break; 144 | default: 145 | throw new ArgumentOutOfRangeException(nameof(type), type, null); 146 | } 147 | 148 | tmpBuffer = sb.ToString(); 149 | }); 150 | 151 | return tmpBuffer; 152 | } 153 | 154 | [DllImport("kanaria.dll", EntryPoint = "to_upper_case_for_utf16", 155 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 156 | private static extern uint ToUpperCase(string target, uint targetSize, StringBuilder result, uint resultSize); 157 | 158 | [DllImport("kanaria.dll", EntryPoint = "to_lower_case_for_utf16", 159 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 160 | private static extern uint ToLowerCase(string target, uint targetSize, StringBuilder result, uint resultSize); 161 | 162 | [DllImport("kanaria.dll", EntryPoint = "to_hiragana_for_utf16", 163 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 164 | private static extern uint ToHiragana(string target, uint targetSize, StringBuilder result, uint resultSize); 165 | 166 | [DllImport("kanaria.dll", EntryPoint = "to_katakana_for_utf16", 167 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 168 | private static extern uint ToKatakana(string target, uint targetSize, StringBuilder result, uint resultSize); 169 | 170 | [DllImport("kanaria.dll", EntryPoint = "to_wide_for_utf16", 171 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 172 | private static extern uint ToWide(string target, uint targetSize, StringBuilder result, uint resultSize, uint convertTarget); 173 | 174 | [DllImport("kanaria.dll", EntryPoint = "to_narrow_for_utf16", 175 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 176 | private static extern uint ToNarrow(string target, uint targetSize, StringBuilder result, uint resultSize, uint convertTarget); 177 | 178 | private enum RequestType 179 | { 180 | UpperCase, 181 | LowerCase, 182 | Katakana, 183 | Hiragana, 184 | Wide, 185 | Narrow 186 | } 187 | 188 | private class RequestParameter 189 | { 190 | public RequestType Type { get; set; } 191 | public ConvertTarget ConvertTarget { get; set; } 192 | public RequestParameter(RequestType type, ConvertTarget convertTarget) 193 | { 194 | Type = type; 195 | ConvertTarget = convertTarget; 196 | } 197 | 198 | public RequestParameter(RequestType type) 199 | { 200 | Type = type; 201 | ConvertTarget = ConvertTarget.All; 202 | } 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/src/Utils/AsciiUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Kanaria.Utils 4 | { 5 | public static class AsciiUtils 6 | { 7 | /// 8 | /// ASCII文字かどうかを判定します。 9 | /// 半角・全角かどうかは区別しません。 10 | /// 11 | /// 判定対象 12 | /// 該当:true / 非該当:false 13 | [DllImport("kanaria.dll", EntryPoint = "is_ascii_for_utf16", CallingConvention = CallingConvention.Cdecl, 14 | CharSet = CharSet.Unicode)] 15 | [return:MarshalAs(UnmanagedType.I1)] 16 | public static extern bool IsAscii(char target); 17 | 18 | /// 19 | /// 半角ASCII文字かどうかを判定します。 20 | /// 21 | /// 判定対象 22 | /// 該当:true / 非該当:false 23 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_ascii_for_utf16", 24 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 25 | [return:MarshalAs(UnmanagedType.I1)] 26 | public static extern bool IsNarrowAscii(char target); 27 | 28 | /// 29 | /// 全角ASCII文字かどうかを判定します。 30 | /// 31 | /// 判定対象 32 | /// 該当:true / 非該当:false 33 | [DllImport("kanaria.dll", EntryPoint = "is_wide_ascii_for_utf16", 34 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 35 | [return:MarshalAs(UnmanagedType.I1)] 36 | public static extern bool IsWideAscii(char target); 37 | 38 | /// 39 | /// アルファベット小文字かどうかを判定します。 40 | /// 41 | /// 判定対象 42 | /// 該当:true / 非該当:false 43 | [DllImport("kanaria.dll", EntryPoint = "is_lower_case_for_utf16", 44 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 45 | [return:MarshalAs(UnmanagedType.I1)] 46 | public static extern bool IsLowerCase(char target); 47 | 48 | /// 49 | /// 半角アルファベット小文字かどうかを判定します。 50 | /// 51 | /// 判定対象 52 | /// 該当:true / 非該当:false 53 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_lower_case_for_utf16", 54 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 55 | [return:MarshalAs(UnmanagedType.I1)] 56 | public static extern bool IsNarrowLowerCase(char target); 57 | 58 | /// 59 | /// 全角アルファベット小文字かどうかを判定します。 60 | /// 61 | /// 判定対象 62 | /// 該当:true / 非該当:false 63 | [DllImport("kanaria.dll", EntryPoint = "is_wide_lower_case_for_utf16", 64 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 65 | [return:MarshalAs(UnmanagedType.I1)] 66 | public static extern bool IsWideLowerCase(char target); 67 | 68 | /// 69 | /// アルファベット大文字かどうかを判定します。 70 | /// 71 | /// 判定対象 72 | /// 該当:true / 非該当:false 73 | [DllImport("kanaria.dll", EntryPoint = "is_upper_case_for_utf16", 74 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 75 | [return:MarshalAs(UnmanagedType.I1)] 76 | public static extern bool IsUpperCase(char target); 77 | 78 | /// 79 | /// 半角アルファベット大文字かどうかを判定します。 80 | /// 81 | /// 判定対象 82 | /// 該当:true / 非該当:false 83 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_upper_case_for_utf16", 84 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 85 | [return:MarshalAs(UnmanagedType.I1)] 86 | public static extern bool IsNarrowUpperCase(char target); 87 | 88 | /// 89 | /// 全角アルファベット大文字かどうかを判定します。 90 | /// 91 | /// 判定対象 92 | /// 該当:true / 非該当:false 93 | [DllImport("kanaria.dll", EntryPoint = "is_wide_upper_case_for_utf16", 94 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 95 | [return:MarshalAs(UnmanagedType.I1)] 96 | public static extern bool IsWideUpperCase(char target); 97 | 98 | /// 99 | /// 記号かどうかを判定します(ASCIIの範囲内のみ)。 100 | /// 半角・全角は区別しません。 101 | /// 102 | /// 判定対象 103 | /// 該当:true / 非該当:false 104 | [DllImport("kanaria.dll", EntryPoint = "is_ascii_symbol_for_utf16", 105 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 106 | [return:MarshalAs(UnmanagedType.I1)] 107 | public static extern bool IsAsciiSymbol(char target); 108 | 109 | 110 | /// 111 | /// 半角記号かどうかを判定します(ASCIIの範囲内のみ)。 112 | /// 113 | /// 判定対象 114 | /// 該当:true / 非該当:false 115 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_ascii_symbol_for_utf16", 116 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 117 | [return:MarshalAs(UnmanagedType.I1)] 118 | public static extern bool IsNarrowAsciiSymbol(char target); 119 | 120 | /// 121 | /// 全角記号かどうかを判定します(ASCIIの範囲内のみ)。 122 | /// 123 | /// 判定対象 124 | /// 該当:true / 非該当:false 125 | [DllImport("kanaria.dll", EntryPoint = "is_wide_ascii_symbol_for_utf16", 126 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 127 | [return:MarshalAs(UnmanagedType.I1)] 128 | public static extern bool IsWideAsciiSymbol(char target); 129 | 130 | /// 131 | /// 数字かどうかを判定します。 132 | /// 半角・全角は区別しません。 133 | /// 134 | /// 判定対象 135 | /// 該当:true / 非該当:false 136 | [DllImport("kanaria.dll", EntryPoint = "is_number_for_utf16", CallingConvention = CallingConvention.Cdecl, 137 | CharSet = CharSet.Unicode)] 138 | [return:MarshalAs(UnmanagedType.I1)] 139 | public static extern bool IsNumber(char target); 140 | 141 | /// 142 | /// 半角数字かどうかを判定します。 143 | /// 144 | /// 判定対象 145 | /// 該当:true / 非該当:false 146 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_number_for_utf16", 147 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 148 | [return:MarshalAs(UnmanagedType.I1)] 149 | public static extern bool IsNarrowNumber(char target); 150 | 151 | /// 152 | /// 全角数字かどうかを判定します。 153 | /// 154 | /// 判定対象 155 | /// 該当:true / 非該当:false 156 | [DllImport("kanaria.dll", EntryPoint = "is_wide_number_for_utf16", 157 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 158 | [return:MarshalAs(UnmanagedType.I1)] 159 | public static extern bool IsWideNumber(char target); 160 | 161 | 162 | /// 163 | /// 小文字を大文字に変換します。 164 | /// 半角・全角は区別しません。 165 | /// 166 | /// 対象文字 167 | /// 変換後文字 168 | [DllImport("kanaria.dll", EntryPoint = "convert_to_upper_case_for_utf16", 169 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 170 | [return:MarshalAs(UnmanagedType.U2)] 171 | public static extern char ConvertToUpperCase(char target); 172 | 173 | /// 174 | /// 大文字を小文字に変換します。 175 | /// 半角・全角は区別しません。 176 | /// 177 | /// 対象文字 178 | /// 変換後文字 179 | [DllImport("kanaria.dll", EntryPoint = "convert_to_lower_case_for_utf16", 180 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 181 | [return:MarshalAs(UnmanagedType.U2)] 182 | public static extern char ConvertToLowerCase(char target); 183 | } 184 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/src/Utils/KanaUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Kanaria.Utils 4 | { 5 | public static class KanaUtils 6 | { 7 | /// 8 | /// ひらがなかどうかを判定します。 9 | /// 10 | /// 判定対象 11 | /// 該当:true / 非該当:false 12 | [DllImport("kanaria.dll", EntryPoint = "is_hiragana_for_utf16", 13 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 14 | [return:MarshalAs(UnmanagedType.I1)] 15 | public static extern bool IsHiragana(char target); 16 | 17 | /// 18 | /// カタカナかどうかを判定します。 19 | /// 半角・全角は区別しません。 20 | /// また、対となる変換先のひらがなの有無も考慮しません。 21 | /// 22 | /// 判定対象 23 | /// 該当:true / 非該当:false 24 | [DllImport("kanaria.dll", EntryPoint = "is_katakana_for_utf16", 25 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 26 | [return:MarshalAs(UnmanagedType.I1)] 27 | public static extern bool IsKatakana(char target); 28 | 29 | /// 30 | /// 半角カタカナかどうかを判定します。対となる変換先のひらがなの有無は考慮しません。 31 | /// 32 | /// 判定対象 33 | /// 該当:true / 非該当:false 34 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_katakana_for_utf16", 35 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 36 | [return:MarshalAs(UnmanagedType.I1)] 37 | public static extern bool IsNarrowKatakana(char target); 38 | 39 | /// 40 | /// 全角カタカナかどうかを判定します。対となる変換先のひらがなの有無は考慮しません。 41 | /// 42 | /// 判定対象 43 | /// 該当:true / 非該当:false 44 | [DllImport("kanaria.dll", EntryPoint = "is_wide_katakana_for_utf16", 45 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 46 | [return:MarshalAs(UnmanagedType.I1)] 47 | public static extern bool IsWideKatakana(char target); 48 | 49 | /// 50 | /// 記号かどうかを判定します。 51 | /// 半角・全角は区別しません。 52 | /// ただし、ASCIIコードに属さない、かつJISコードに所属する記号が対象です。 53 | /// 54 | /// 判定対象 55 | /// 該当:true / 非該当:false 56 | [DllImport("kanaria.dll", EntryPoint = "is_jis_symbol", 57 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 58 | [return:MarshalAs(UnmanagedType.I1)] 59 | public static extern bool IsJisSymbol(char target); 60 | 61 | /// 62 | /// 半角記号かどうかを判定します。 63 | /// ただし、ASCIIコードに属さない、かつJISコードに所属する記号が対象です。 64 | /// 65 | /// 判定対象 66 | /// 該当:true / 非該当:false 67 | [DllImport("kanaria.dll", EntryPoint = "is_narrow_jis_symbol_for_utf16", 68 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 69 | [return:MarshalAs(UnmanagedType.I1)] 70 | public static extern bool IsNarrowJisSymbol(char target); 71 | 72 | /// 73 | /// 全角記号かどうかを判定します。 74 | /// ただし、ASCIIコードに属さない、かつJISコードに所属する記号が対象です。 75 | /// 76 | /// 判定対象 77 | /// 該当:true / 非該当:false 78 | [DllImport("kanaria.dll", EntryPoint = "is_wide_jis_symbol_for_utf16", 79 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 80 | [return:MarshalAs(UnmanagedType.I1)] 81 | public static extern bool IsWideJisSymbol(char target); 82 | 83 | /// 84 | /// 全角カタカナではあるが、対となる変換先のひらがながある文字かどうかを判定します。 85 | /// 86 | /// 判定対象 87 | /// 該当:true / 非該当:false 88 | [DllImport("kanaria.dll", EntryPoint = "is_can_convert_hiragana_for_utf16", 89 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 90 | [return:MarshalAs(UnmanagedType.I1)] 91 | public static extern bool IsCanShiftToHiragana(char target); 92 | 93 | /// 94 | /// 全角カタカナをひらがなに変換します。 95 | /// 96 | /// 変換対象文字 97 | /// 変換後文字 98 | [DllImport("kanaria.dll", EntryPoint = "convert_to_hiragana_for_utf16", 99 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 100 | [return:MarshalAs(UnmanagedType.U2)] 101 | public static extern char ConvertToHiragana(char target); 102 | 103 | /// 104 | /// ひらがなを全角カタカナに変換します。 105 | /// 106 | /// 変換対象文字 107 | /// 変換後文字 108 | [DllImport("kanaria.dll", EntryPoint = "convert_to_katakana_for_utf16", 109 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 110 | [return:MarshalAs(UnmanagedType.U2)] 111 | public static extern char ConvertToKatakana(char target); 112 | } 113 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaDotNet/src/Utils/WidthUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Kanaria.Utils 4 | { 5 | public static class WidthUtils 6 | { 7 | /// 8 | /// 全角文字を半角に変換します。 9 | /// 一文字目と二文字目が結合可能だった場合、結合済みの文字列を返却します。 10 | /// 文字列が結合された場合、2つ目の戻り値にtrueが入っています。 11 | /// 12 | /// 変換対象文字 13 | /// 次の文字。濁音・半濁音のように結合可能な文字の場合、targetとこの値を結合する。 14 | /// 結合あり:true / 結合なし:false 15 | /// 変換後文字 16 | [DllImport("kanaria.dll", EntryPoint = "convert_to_wide_for_utf16", 17 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 18 | [return:MarshalAs(UnmanagedType.U2)] 19 | public static extern char ConvertToWide(char target, char next, out bool is_pad); 20 | 21 | /// 22 | /// 全角文字を半角に変換します。 23 | /// 全角カタカナの濁音文字など、戻り値が2文字分になる場合もあります。 24 | /// 戻り値が1文字のときは2文字目にはヌル文字相当の値が入っています。 25 | /// 26 | /// 変換対象文字 27 | /// 濁音記号等で増えた文字。増えなかった場合はnull文字(\u0000)。 28 | /// 変換後文字 29 | [DllImport("kanaria.dll", EntryPoint = "convert_to_narrow_for_utf16", 30 | CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 31 | [return:MarshalAs(UnmanagedType.U2)] 32 | public static extern char ConvertToNarrow(char target, out char second); 33 | } 34 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaSample/KanariaSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net40 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaSample/src/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CommandLine; 4 | using Kanaria; 5 | 6 | namespace KanariaSample 7 | { 8 | internal static class Program { 9 | public static void Main(string[] args) 10 | { 11 | Parser.Default.ParseArguments(args).WithParsed(arguments => 12 | { 13 | if (arguments.Platform) 14 | { 15 | PrintPlatform(); 16 | } 17 | 18 | PrintConvertResult(arguments.Text, arguments.Request); 19 | }); 20 | } 21 | 22 | private static void PrintPlatform() 23 | { 24 | switch (IntPtr.Size) 25 | { 26 | case 4: 27 | Console.WriteLine("x86で動作中…"); 28 | break; 29 | case 8: 30 | Console.WriteLine("x64で動作中…"); 31 | break; 32 | default: 33 | throw new PlatformNotSupportedException(); 34 | } 35 | } 36 | 37 | private static void PrintConvertResult(string src, string options) 38 | { 39 | var ucsStr = UcsString.From(src); 40 | options.ToList().ForEach(request => 41 | { 42 | switch (request) 43 | { 44 | case 'u': 45 | ucsStr = ucsStr.UpperCase(); 46 | break; 47 | case 'l': 48 | ucsStr = ucsStr.LowerCase(); 49 | break; 50 | case 'h': 51 | ucsStr = ucsStr.Hiragana(); 52 | break; 53 | case 'k': 54 | ucsStr = ucsStr.Katakana(); 55 | break; 56 | case 'w': 57 | ucsStr = ucsStr.Wide(); 58 | break; 59 | case 'n': 60 | ucsStr = ucsStr.Narrow(); 61 | break; 62 | } 63 | }); 64 | Console.WriteLine(ucsStr); 65 | } 66 | 67 | public class Arguments 68 | { 69 | [Value(0, HelpText = "かな変換などを試したい文字列を設定してください。", Required = true)] 70 | public string Text { get; set; } 71 | 72 | [Option('c', "convert", Required = true, HelpText = "変換先を設定します。設定値:大文字(u)/小文字(l)/ひらがな(h)/カタカナ(k)/全角(w)/半角(n)")] 73 | public string Request { get; set; } 74 | 75 | [Option('p', "platform", Required = false, HelpText = "x86/x64のうちどちらで動いているかを表示します。")] 76 | public bool Platform { get; set; } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaTest/ExampleText.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace KanariaTest { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class ExampleText { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal ExampleText() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KanariaTest.ExampleText", typeof(ExampleText).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to 65 | ///Chief Justice Roberts, President Carter, President Clinton, President Bush, President Obama, fellow Americans, and people of the world: 66 | ///thank you. 67 | ///We, the citizens of America, are now joined in a great national effort to rebuild our country and to restore its promise for all of our people. 68 | ///Together, we will determine the course of America and the world for years to come. 69 | ///We will face challenges. We will confront hardships. But we will get the job done.Every four years, we gather on these steps to carr [rest of string was truncated]";. 70 | /// 71 | internal static string TRUMP { 72 | get { 73 | return ResourceManager.GetString("TRUMP", resourceCulture); 74 | } 75 | } 76 | 77 | /// 78 | /// Looks up a localized string similar to 79 | ///吾輩は猫である 80 | ///夏目漱石 81 | /// 82 | ///一 83 | /// 84 | /// 吾輩は猫である。名前はまだ無い。 85 | /// どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。 86 | /// この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくする [rest of string was truncated]";. 87 | /// 88 | internal static string WAGAHAI { 89 | get { 90 | return ResourceManager.GetString("WAGAHAI", resourceCulture); 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaTest/KanariaTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | false 6 | 7 | 8 8 | 9 | enable 10 | 11 | net472 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaTest/src/Benchmark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using Kanaria; 6 | using KanariaTest.External; 7 | using Microsoft.VisualBasic; 8 | using NUnit.Framework; 9 | 10 | namespace KanariaTest 11 | { 12 | public class KanaConverterBenchmark 13 | { 14 | [Test] 15 | public void Wagahai_Katakana_Test() 16 | { 17 | Bench(ExampleText.WAGAHAI, 10, new[] 18 | { 19 | new KeyValuePair>("StrConv", targetText => 20 | { 21 | return Strings.StrConv(targetText, VbStrConv.Katakana, 0x411); 22 | }), 23 | new KeyValuePair>("kanaxs", targetText => 24 | { 25 | return Kana.ToKatakana(targetText); 26 | }), 27 | new KeyValuePair>("KanariaDotNet", targetText => 28 | { 29 | return UcsString.From(targetText).Katakana().ToString(); 30 | }), 31 | }); 32 | } 33 | 34 | [Test] 35 | public void Wagahai_HiraganaKatakana_Hankaku_Test() 36 | { 37 | Bench(ExampleText.WAGAHAI, 10, new[] 38 | { 39 | new KeyValuePair>("StrConv", targetText => 40 | { 41 | var s = Strings.StrConv(targetText, VbStrConv.Hiragana, 0x411); 42 | s = Strings.StrConv(s, VbStrConv.Katakana, 0x411); 43 | return Strings.StrConv(s, VbStrConv.Narrow, 0x411); 44 | }), 45 | new KeyValuePair>("kanaxs", targetText => 46 | { 47 | var s = Kana.ToHiragana(targetText); 48 | s = Kana.ToKatakana(s); 49 | return Kana.ToHankakuKana(s); 50 | }), 51 | new KeyValuePair>("KanariaDotNet", targetText => 52 | { 53 | return UcsString.From(targetText) 54 | .Hiragana() 55 | .Katakana() 56 | .Narrow() 57 | .ToString(); 58 | }), 59 | }); 60 | } 61 | 62 | [Test] 63 | public void Wagahai_HiraganaKatakana_HankakuZenkaku_Test() 64 | { 65 | Bench(ExampleText.WAGAHAI, 10, new[] 66 | { 67 | new KeyValuePair>("StrConv", targetText => 68 | { 69 | var s = Strings.StrConv(targetText, VbStrConv.Hiragana, 0x411); 70 | s = Strings.StrConv(s, VbStrConv.Katakana, 0x411); 71 | s = Strings.StrConv(s, VbStrConv.Narrow, 0x411); 72 | return Strings.StrConv(s, VbStrConv.Wide, 0x411); 73 | }), 74 | new KeyValuePair>("kanaxs", targetText => 75 | { 76 | var s = Kana.ToHiragana(targetText); 77 | s = Kana.ToKatakana(s); 78 | s = Kana.ToHankakuKana(s); 79 | return Kana.ToZenkakuKana(s); 80 | }), 81 | new KeyValuePair>("KanariaDotNet", targetText => 82 | { 83 | return UcsString.From(targetText) 84 | .Hiragana() 85 | .Katakana() 86 | .Narrow() 87 | .Wide() 88 | .ToString(); 89 | }), 90 | }); 91 | } 92 | 93 | [Test] 94 | public void Wagahai_Katakana_HankakuZenkaku_Test() 95 | { 96 | Bench(ExampleText.WAGAHAI, 10, new[] 97 | { 98 | new KeyValuePair>("StrConv", targetText => 99 | { 100 | var s = Strings.StrConv(targetText, VbStrConv.Katakana, 0x411); 101 | s = Strings.StrConv(s, VbStrConv.Narrow, 0x411); 102 | return Strings.StrConv(s, VbStrConv.Wide, 0x411); 103 | }), 104 | new KeyValuePair>("kanaxs", targetText => 105 | { 106 | var s = Kana.ToKatakana(targetText); 107 | s = Kana.ToHankakuKana(s); 108 | return Kana.ToZenkakuKana(s); 109 | }), 110 | new KeyValuePair>("KanariaDotNet", targetText => 111 | { 112 | return UcsString.From(targetText) 113 | .Katakana() 114 | .Narrow() 115 | .Wide() 116 | .ToString(); 117 | }), 118 | }); 119 | } 120 | 121 | [Test] 122 | public void Trump_LowerUpper_Test() 123 | { 124 | Bench(ExampleText.TRUMP, 10, new[] 125 | { 126 | new KeyValuePair>("StrConv", targetText => 127 | { 128 | var s = Strings.StrConv(targetText, VbStrConv.Lowercase, 0x411); 129 | return Strings.StrConv(s, VbStrConv.Uppercase, 0x411); 130 | }), 131 | new KeyValuePair>("dotnet", targetText => 132 | { 133 | var s = targetText.ToLower(); 134 | return s.ToUpper(); 135 | }), 136 | new KeyValuePair>("KanariaDotNet", targetText => 137 | { 138 | return UcsString.From(targetText) 139 | .LowerCase() 140 | .UpperCase() 141 | .ToString(); 142 | }), 143 | }); 144 | } 145 | 146 | [Test] 147 | public void Trump_WideNarrow_Test() 148 | { 149 | Bench(ExampleText.TRUMP, 10, new[] 150 | { 151 | new KeyValuePair>("StrConv", targetText => 152 | { 153 | var s = Strings.StrConv(targetText, VbStrConv.Wide, 0x411); 154 | s = Strings.StrConv(s, VbStrConv.Narrow, 0x411); 155 | return s; 156 | }), 157 | new KeyValuePair>("Kanaxs", targetText => 158 | { 159 | var s = Kana.ToZenkaku(targetText); 160 | s = Kana.ToHankaku(s); 161 | return s; 162 | }), 163 | new KeyValuePair>("KanariaDotNet", targetText => 164 | { 165 | return UcsString.From(targetText) 166 | .Wide() 167 | .Narrow() 168 | .ToString(); 169 | }), 170 | }); 171 | } 172 | 173 | private void Bench(string s, int maxCount, IEnumerable>> routines) 174 | { 175 | //Parallel.ForEach(routines, routine => 176 | routines 177 | .ToList() 178 | .ForEach(routine => 179 | { 180 | var stopWatch = Stopwatch.StartNew(); 181 | Enumerable 182 | .Range(0, maxCount) 183 | .ToList() 184 | .ForEach(i => routine.Value(s)); 185 | stopWatch.Stop(); 186 | 187 | Console.WriteLine($@"{routine.Key} : {stopWatch.ElapsedTicks.ToString()}"); 188 | }); 189 | } 190 | } 191 | } -------------------------------------------------------------------------------- /kanaria_dotnet/KanariaTest/src/ExampleSentenceTest.cs: -------------------------------------------------------------------------------- 1 | using Kanaria; 2 | using Kanaria.Utils; 3 | using NUnit.Framework; 4 | 5 | namespace KanariaTest 6 | { 7 | public class ExampleSentenceTest 8 | { 9 | [Test] 10 | public void ExampleSentence1() 11 | { 12 | var hankaku = "チタタプ トテトテFoooo!!!11!"; 13 | var zenkaku = "チタタプ トテトテFoooo!!!11!"; 14 | Assert.AreEqual(hankaku, UcsString.From(zenkaku).Narrow().ToString()); 15 | Assert.AreEqual(zenkaku, UcsString.From(hankaku).Wide().ToString()); 16 | } 17 | 18 | [Test] 19 | public void ExampleSentence2() 20 | { 21 | var hankaku = "吾輩ハ😺猫デアル😺"; 22 | var zenkaku = "吾輩ハ😺猫デアル😺"; 23 | Assert.AreEqual(hankaku, UcsString.From(zenkaku).Narrow().ToString()); 24 | Assert.AreEqual(zenkaku, UcsString.From(hankaku).Wide().ToString()); 25 | } 26 | 27 | [Test] 28 | public void ExampleSentence3() 29 | { 30 | var hankaku = "フジサンコポォ"; 31 | var zenkaku = "フジサンコポォ"; 32 | Assert.AreEqual(hankaku, UcsString.From(zenkaku).Narrow().ToString()); 33 | Assert.AreEqual(zenkaku, UcsString.From(hankaku).Wide().ToString()); 34 | } 35 | 36 | 37 | [Test] 38 | public void ExampleSentence4() 39 | { 40 | var katakana = "チタタプ トテトテ"; 41 | var hiragana = "ちたたぷ とてとて"; 42 | Assert.AreEqual(katakana, UcsString.From(hiragana).Katakana().ToString()); 43 | Assert.AreEqual(hiragana, UcsString.From(katakana).Hiragana().ToString()); 44 | } 45 | 46 | [Test] 47 | public void ExampleSentence5() 48 | { 49 | var katakana = "吾輩ハ😺猫デアル😺"; 50 | var hiragana = "吾輩は😺猫である😺"; 51 | Assert.AreEqual(katakana, UcsString.From(hiragana).Katakana().ToString()); 52 | Assert.AreEqual(hiragana, UcsString.From(katakana).Hiragana().ToString()); 53 | } 54 | 55 | [Test] 56 | public void ExampleSentence6() 57 | { 58 | Assert.True(AsciiUtils.IsAscii('a')); 59 | Assert.True(AsciiUtils.IsWideAscii('w')); 60 | Assert.True(AsciiUtils.IsNarrowAscii('n')); 61 | Assert.False(AsciiUtils.IsAscii('あ')); 62 | Assert.False(AsciiUtils.IsWideAscii('漢')); 63 | Assert.False(AsciiUtils.IsNarrowAscii('ア')); 64 | 65 | Assert.True(AsciiUtils.IsLowerCase('a')); 66 | Assert.True(AsciiUtils.IsWideLowerCase('w')); 67 | Assert.True(AsciiUtils.IsNarrowLowerCase('n')); 68 | Assert.False(AsciiUtils.IsLowerCase('A')); 69 | Assert.False(AsciiUtils.IsWideLowerCase('n')); 70 | Assert.False(AsciiUtils.IsNarrowLowerCase('w')); 71 | 72 | Assert.True(AsciiUtils.IsUpperCase('A')); 73 | Assert.True(AsciiUtils.IsWideUpperCase('W')); 74 | Assert.True(AsciiUtils.IsNarrowUpperCase('N')); 75 | Assert.False(AsciiUtils.IsUpperCase('a')); 76 | Assert.False(AsciiUtils.IsWideUpperCase('w')); 77 | Assert.False(AsciiUtils.IsNarrowUpperCase('n')); 78 | 79 | Assert.True(AsciiUtils.IsAsciiSymbol('*')); 80 | Assert.True(AsciiUtils.IsWideAsciiSymbol('@')); 81 | Assert.True(AsciiUtils.IsNarrowAsciiSymbol('@')); 82 | Assert.False(AsciiUtils.IsAsciiSymbol('、')); 83 | Assert.False(AsciiUtils.IsWideAsciiSymbol('@')); 84 | Assert.False(AsciiUtils.IsNarrowAsciiSymbol('@')); 85 | 86 | Assert.True(AsciiUtils.IsNumber('0')); 87 | Assert.True(AsciiUtils.IsWideNumber('0')); 88 | Assert.True(AsciiUtils.IsNarrowNumber('1')); 89 | Assert.False(AsciiUtils.IsNumber('a')); 90 | Assert.False(AsciiUtils.IsWideNumber('1')); 91 | Assert.False(AsciiUtils.IsNarrowNumber('0')); 92 | 93 | Assert.AreEqual('a', AsciiUtils.ConvertToLowerCase('A')); 94 | Assert.AreEqual('A', AsciiUtils.ConvertToUpperCase('a')); 95 | Assert.AreEqual('あ', AsciiUtils.ConvertToLowerCase('あ')); 96 | Assert.AreEqual('0', AsciiUtils.ConvertToUpperCase('0')); 97 | } 98 | 99 | [Test] 100 | public void ExampleSentence7() 101 | { 102 | Assert.True(KanaUtils.IsHiragana('あ')); 103 | Assert.False(KanaUtils.IsHiragana('ア')); 104 | 105 | Assert.True(KanaUtils.IsKatakana('ア')); 106 | Assert.True(KanaUtils.IsWideKatakana('カ')); 107 | Assert.True(KanaUtils.IsNarrowKatakana('サ')); 108 | Assert.False(KanaUtils.IsKatakana('あ')); 109 | Assert.False(KanaUtils.IsWideKatakana('カ')); 110 | Assert.False(KanaUtils.IsNarrowKatakana('サ')); 111 | 112 | Assert.True(KanaUtils.IsJisSymbol('ゟ')); 113 | Assert.True(KanaUtils.IsWideJisSymbol('・')); 114 | Assert.True(KanaUtils.IsNarrowJisSymbol('・')); 115 | Assert.False(KanaUtils.IsJisSymbol('@')); 116 | Assert.False(KanaUtils.IsWideJisSymbol('・')); 117 | Assert.False(KanaUtils.IsNarrowJisSymbol('・')); 118 | 119 | Assert.True(KanaUtils.IsCanShiftToHiragana('ワ')); 120 | Assert.False(KanaUtils.IsCanShiftToHiragana('ヷ')); 121 | 122 | Assert.AreEqual('あ', KanaUtils.ConvertToHiragana('ア')); 123 | Assert.AreEqual('ア', KanaUtils.ConvertToKatakana('あ')); 124 | Assert.AreEqual('ア', KanaUtils.ConvertToHiragana('ア')); 125 | Assert.AreEqual('漢', KanaUtils.ConvertToKatakana('漢')); 126 | } 127 | 128 | [Test] 129 | public void ExampleSentence8() 130 | { 131 | var isPad = false; 132 | 133 | Assert.AreEqual('ア', WidthUtils.ConvertToWide('ア', (char) 0, out isPad)); 134 | Assert.False(isPad); 135 | 136 | Assert.AreEqual('ガ', WidthUtils.ConvertToWide('カ', '゙', out isPad)); 137 | Assert.True(isPad); 138 | 139 | Assert.AreEqual('カ', WidthUtils.ConvertToWide('カ', '゚', out isPad)); 140 | Assert.False(isPad); 141 | 142 | Assert.AreEqual('あ', WidthUtils.ConvertToWide('あ', (char) 0, out isPad)); 143 | Assert.False(isPad); 144 | 145 | var second = char.MaxValue; 146 | 147 | Assert.AreEqual('ア', WidthUtils.ConvertToNarrow('ア', out second)); 148 | Assert.AreEqual((char) 0, second); 149 | 150 | Assert.AreEqual('カ', WidthUtils.ConvertToNarrow('ガ', out second)); 151 | Assert.AreEqual('゙', second); 152 | 153 | Assert.AreEqual('ハ', WidthUtils.ConvertToNarrow('パ', out second)); 154 | Assert.AreEqual('゚', second); 155 | 156 | Assert.AreEqual('あ', WidthUtils.ConvertToNarrow('あ', out second)); 157 | Assert.AreEqual((char) 0, second); 158 | 159 | Assert.AreEqual('カ', WidthUtils.ConvertToNarrow('ガ', out second)); 160 | Assert.AreNotEqual((char) 0, second); 161 | Assert.AreNotEqual('゚', second); 162 | } 163 | 164 | [Test] 165 | public void ExampleSentence9() { 166 | var source = "吾輩は😺猫である😺"; 167 | var expect = "吾輩ハ😺猫デアル😺"; 168 | var expect2 = "吾輩ハ😺猫デアル😺"; 169 | 170 | Assert.AreEqual(expect, UcsString.From(source).Katakana().Narrow(ConvertTarget.All).ToString()); 171 | Assert.AreEqual(expect2, UcsString.From(source).Katakana().Narrow(ConvertTarget.Number | ConvertTarget.Symbol | ConvertTarget.Alphabet).ToString()); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /kanaria_dotnet/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.nio.file.Files 2 | import java.nio.file.Paths 3 | 4 | plugins { 5 | id("com.osm.gradle.plugins.rustic") version "0.2.7" 6 | } 7 | 8 | rustic { 9 | projectSettings.projectLocation("$rootDir/kanaria_extern") 10 | defaultConfig.defaultOptions.apply { 11 | jobs(8) 12 | } 13 | 14 | flavors { 15 | create("x86") { 16 | environments(mapOf( 17 | "AR" to "/usr/bin/i686-w64-mingw32-gcc-ar", 18 | "CC" to "/usr/bin/i686-w64-mingw32-gcc" 19 | )) 20 | defaultOptions.apply { 21 | target("i686-pc-windows-gnu") 22 | cargoConfig.targetTriple.rustFlags(listOf("-C", "panic=abort")) 23 | } 24 | } 25 | 26 | create("x86_64") { 27 | environments(mapOf( 28 | "AR" to "/usr/bin/x86_64-w64-mingw32-gcc-ar", 29 | "CC" to "/usr/bin/x86_64-w64-mingw32-gcc" 30 | )) 31 | defaultOptions.apply { 32 | target("x86_64-pc-windows-gnu") 33 | } 34 | } 35 | } 36 | 37 | variants.all { 38 | if (enabled == false) { 39 | // 無効化されているvariantは処理しない 40 | return@all 41 | } 42 | 43 | deployReleaseOutputs(tasks, this) 44 | } 45 | } 46 | 47 | fun deployReleaseOutputs(tasks: TaskContainer, variant: com.osm.gradle.plugins.types.variants.BuildVariant) { 48 | val target = variant.buildOptions.target 49 | val flavor = variant.flavor 50 | val buildTask = tasks["rustBuild${variant.name}"] 51 | if (buildTask == null || target == null || flavor == null) { 52 | println("[${variant.name}] missing parameters.") 53 | return 54 | } 55 | 56 | if (variant.buildOptions.release == false) { 57 | println("[${variant.name}] release build only.") 58 | return 59 | } 60 | 61 | // CCに指定したものをlinkerに流用 62 | flavor.defaultOptions.cargoConfig.targetTriple.linker(variant.environments?.get("CC")) 63 | 64 | // variants#all()の実行時点ではビルドが走っておらず成果物がないため、 65 | // ビルドの後処理としてコピー処理を設定する 66 | val bit = if (target.contains("x86_64")) "64" else "32" 67 | val srcFilePath = Paths.get("$rootDir/kanaria_extern/target/$target/release", "kanaria.dll") 68 | val dstFilePath = Paths.get("$projectDir/KanariaDotNet/costura${bit}/", "kanaria.dll") 69 | buildTask.doLast { 70 | if (!Files.exists(dstFilePath.parent)) { 71 | Files.createDirectories(dstFilePath.parent) 72 | } 73 | if (Files.exists(dstFilePath)) { 74 | Files.delete(dstFilePath) 75 | } 76 | println("[${variant.name}] Copy the build output from rustBuild to src/main/resources.") 77 | println("[${variant.name}] copy from : $srcFilePath") 78 | println("[${variant.name}] copy to : $dstFilePath") 79 | Files.copy(srcFilePath, dstFilePath) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /kanaria_dotnet/kanaria_dotnet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29613.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KanariaDotNet", "KanariaDotNet\KanariaDotNet.csproj", "{0837E5A3-1977-4A3E-916E-B3BBF83FBEE0}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KanariaTest", "KanariaTest\KanariaTest.csproj", "{F289D0FA-53E5-44BE-8E5A-2754A6950772}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KanariaSample", "KanariaSample\KanariaSample.csproj", "{508467DF-5649-491E-9ACC-C2943BA7AACF}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {0837E5A3-1977-4A3E-916E-B3BBF83FBEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {0837E5A3-1977-4A3E-916E-B3BBF83FBEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {0837E5A3-1977-4A3E-916E-B3BBF83FBEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {0837E5A3-1977-4A3E-916E-B3BBF83FBEE0}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {F289D0FA-53E5-44BE-8E5A-2754A6950772}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F289D0FA-53E5-44BE-8E5A-2754A6950772}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F289D0FA-53E5-44BE-8E5A-2754A6950772}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F289D0FA-53E5-44BE-8E5A-2754A6950772}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {508467DF-5649-491E-9ACC-C2943BA7AACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {508467DF-5649-491E-9ACC-C2943BA7AACF}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {508467DF-5649-491E-9ACC-C2943BA7AACF}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {508467DF-5649-491E-9ACC-C2943BA7AACF}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {69D150E8-90BC-40A1-A523-E7DA61298D23} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /kanaria_dotnet/kanaria_dotnet.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /kanaria_extern/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/rust 2 | # Edit at https://www.gitignore.io/?templates=rust 3 | 4 | ### Rust ### 5 | # Generated by Cargo 6 | # will have compiled files and executables 7 | /target/ 8 | 9 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 10 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 11 | Cargo.lock 12 | 13 | # These are backup files generated by rustfmt 14 | **/*.rs.bk 15 | 16 | # End of https://www.gitignore.io/api/rust -------------------------------------------------------------------------------- /kanaria_extern/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kanaria_extern" 3 | version = "0.1.0" 4 | authors = ["samunohito <46447427+samunohito@users.noreply.github.com>"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | kanaria = { path = "../kanaria_core" } 9 | 10 | [lib] 11 | name = "kanaria" 12 | path = "src/lib.rs" 13 | crate-type = ["cdylib"] 14 | -------------------------------------------------------------------------------- /kanaria_extern/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.osm.gradle.plugins.rustic") version "0.2.7" 3 | } 4 | 5 | rustic { 6 | rustic { 7 | projectSettings.projectLocation(projectDir.toString()) 8 | defaultConfig.defaultOptions.jobs(8) 9 | } 10 | } -------------------------------------------------------------------------------- /kanaria_extern/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod utf16; -------------------------------------------------------------------------------- /kanaria_extern/src/utf16/checker.rs: -------------------------------------------------------------------------------- 1 | use kanaria::utils::{AsciiUtils, KanaUtils, WidthUtils}; 2 | 3 | #[no_mangle] 4 | pub unsafe extern "C" fn is_ascii_for_utf16(target: u16) -> bool { 5 | AsciiUtils::is_ascii(target) 6 | } 7 | 8 | #[no_mangle] 9 | pub unsafe extern "C" fn is_narrow_ascii_for_utf16(target: u16) -> bool { 10 | AsciiUtils::is_narrow_ascii(target) 11 | } 12 | 13 | #[no_mangle] 14 | pub unsafe extern "C" fn is_wide_ascii_for_utf16(target: u16) -> bool { 15 | AsciiUtils::is_wide_ascii(target) 16 | } 17 | 18 | #[no_mangle] 19 | pub unsafe extern "C" fn is_lower_case_for_utf16(target: u16) -> bool { 20 | AsciiUtils::is_lower_case(target) 21 | } 22 | 23 | #[no_mangle] 24 | pub unsafe extern "C" fn is_narrow_lower_case_for_utf16(target: u16) -> bool { 25 | AsciiUtils::is_narrow_lower_case(target) 26 | } 27 | 28 | #[no_mangle] 29 | pub unsafe extern "C" fn is_wide_lower_case_for_utf16(target: u16) -> bool { 30 | AsciiUtils::is_wide_lower_case(target) 31 | } 32 | 33 | #[no_mangle] 34 | pub unsafe extern "C" fn is_upper_case_for_utf16(target: u16) -> bool { 35 | AsciiUtils::is_upper_case(target) 36 | } 37 | 38 | #[no_mangle] 39 | pub unsafe extern "C" fn is_narrow_upper_case_for_utf16(target: u16) -> bool { 40 | AsciiUtils::is_narrow_upper_case(target) 41 | } 42 | 43 | #[no_mangle] 44 | pub unsafe extern "C" fn is_wide_upper_case_for_utf16(target: u16) -> bool { 45 | AsciiUtils::is_wide_upper_case(target) 46 | } 47 | 48 | #[no_mangle] 49 | pub unsafe extern "C" fn is_ascii_symbol_for_utf16(target: u16) -> bool { 50 | AsciiUtils::is_ascii_symbol(target) 51 | } 52 | 53 | #[no_mangle] 54 | pub unsafe extern "C" fn is_narrow_ascii_symbol_for_utf16(target: u16) -> bool { 55 | AsciiUtils::is_narrow_ascii_symbol(target) 56 | } 57 | 58 | #[no_mangle] 59 | pub unsafe extern "C" fn is_wide_ascii_symbol_for_utf16(target: u16) -> bool { 60 | AsciiUtils::is_wide_ascii_symbol(target) 61 | } 62 | 63 | #[no_mangle] 64 | pub unsafe extern "C" fn is_number_for_utf16(target: u16) -> bool { 65 | AsciiUtils::is_number(target) 66 | } 67 | 68 | #[no_mangle] 69 | pub unsafe extern "C" fn is_narrow_number_for_utf16(target: u16) -> bool { 70 | AsciiUtils::is_narrow_number(target) 71 | } 72 | 73 | #[no_mangle] 74 | pub unsafe extern "C" fn is_wide_number_for_utf16(target: u16) -> bool { 75 | AsciiUtils::is_wide_number(target) 76 | } 77 | 78 | #[no_mangle] 79 | pub unsafe extern "C" fn convert_to_upper_case_for_utf16(target: u16) -> u16 { 80 | AsciiUtils::convert_to_upper_case(target) 81 | } 82 | 83 | #[no_mangle] 84 | pub unsafe extern "C" fn convert_to_lower_case_for_utf16(target: u16) -> u16 { 85 | AsciiUtils::convert_to_lower_case(target) 86 | } 87 | 88 | 89 | 90 | #[no_mangle] 91 | pub unsafe extern "C" fn is_hiragana_for_utf16(target: u16) -> bool { 92 | KanaUtils::is_hiragana(target) 93 | } 94 | 95 | #[no_mangle] 96 | pub unsafe extern "C" fn is_katakana_for_utf16(target: u16) -> bool { 97 | KanaUtils::is_katakana(target) 98 | } 99 | 100 | #[no_mangle] 101 | pub unsafe extern "C" fn is_narrow_katakana_for_utf16(target: u16) -> bool { 102 | KanaUtils::is_narrow_katakana(target) 103 | } 104 | 105 | #[no_mangle] 106 | pub unsafe extern "C" fn is_wide_katakana_for_utf16(target: u16) -> bool { 107 | KanaUtils::is_wide_katakana(target) 108 | } 109 | 110 | #[no_mangle] 111 | pub unsafe extern "C" fn is_jis_symbol(target: u16) -> bool { 112 | KanaUtils::is_jis_symbol(target) 113 | } 114 | 115 | #[no_mangle] 116 | pub unsafe extern "C" fn is_narrow_jis_symbol_for_utf16(target: u16) -> bool { 117 | KanaUtils::is_narrow_jis_symbol(target) 118 | } 119 | 120 | #[no_mangle] 121 | pub unsafe extern "C" fn is_wide_jis_symbol_for_utf16(target: u16) -> bool { 122 | KanaUtils::is_wide_jis_symbol(target) 123 | } 124 | 125 | #[no_mangle] 126 | pub unsafe extern "C" fn is_can_convert_hiragana_for_utf16(target: u16) -> bool { 127 | KanaUtils::is_can_convert_hiragana(target) 128 | } 129 | 130 | #[no_mangle] 131 | pub unsafe extern "C" fn convert_to_hiragana_for_utf16(target: u16) -> u16 { 132 | KanaUtils::convert_to_hiragana(target) 133 | } 134 | 135 | #[no_mangle] 136 | pub unsafe extern "C" fn convert_to_katakana_for_utf16(target: u16) -> u16 { 137 | KanaUtils::convert_to_katakana(target) 138 | } 139 | 140 | 141 | 142 | #[no_mangle] 143 | pub unsafe extern "C" fn convert_to_wide_for_utf16(target: u16, next: u16, is_pad: *mut bool) -> u16 { 144 | let (result_ret, is_pad_ret) = WidthUtils::convert_to_wide(target, next); 145 | is_pad.write(is_pad_ret); 146 | return result_ret; 147 | } 148 | 149 | #[no_mangle] 150 | pub unsafe extern "C" fn convert_to_narrow_for_utf16(target: u16, out_char: *mut u16) -> u16 { 151 | let (first, second) = WidthUtils::convert_to_narrow(target); 152 | out_char.write(second); 153 | return first; 154 | } -------------------------------------------------------------------------------- /kanaria_extern/src/utf16/converter.rs: -------------------------------------------------------------------------------- 1 | use kanaria::constants::*; 2 | use kanaria::string::ConvertType; 3 | use kanaria::string::ConvertType::{Hiragana, Katakana, LowerCase, Narrow, UpperCase, Wide}; 4 | use kanaria::string::UCSStr; 5 | use kanaria::utils::ConvertTarget; 6 | 7 | fn int_to_convert_type(convert_type: u32) -> ConvertType { 8 | match convert_type { 9 | CONVERT_TYPE_UPPER_CASE => UpperCase, 10 | CONVERT_TYPE_LOWER_CASE => LowerCase, 11 | CONVERT_TYPE_HIRAGANA => Hiragana, 12 | CONVERT_TYPE_KATAKANA => Katakana, 13 | CONVERT_TYPE_NARROW => Narrow, 14 | CONVERT_TYPE_WIDE => Wide, 15 | _ => ConvertType::None, 16 | } 17 | } 18 | 19 | #[no_mangle] 20 | pub unsafe extern "C" fn convert_for_utf16( 21 | src_chars_ptr: *const u16, 22 | src_chars_ptr_size: u32, 23 | dst_chars_ptr: *mut u16, 24 | dst_chars_ptr_size: u32, 25 | convert_type: u32, 26 | convert_target: u32, 27 | ) -> u32 { 28 | dst_chars_ptr.write_bytes(0, dst_chars_ptr_size as usize); 29 | return UCSStr::convert_raw( 30 | src_chars_ptr, 31 | dst_chars_ptr, 32 | src_chars_ptr_size as usize, 33 | int_to_convert_type(convert_type), 34 | ConvertTarget::from_bits(convert_target).unwrap_or(ConvertTarget::ALL), 35 | ) as u32; 36 | } 37 | 38 | #[no_mangle] 39 | pub unsafe extern "C" fn to_upper_case_for_utf16( 40 | src_chars_ptr: *const u16, 41 | src_chars_ptr_size: u32, 42 | dst_chars_ptr: *mut u16, 43 | dst_chars_ptr_size: u32, 44 | ) -> u32 { 45 | convert_for_utf16( 46 | src_chars_ptr, 47 | src_chars_ptr_size, 48 | dst_chars_ptr, 49 | dst_chars_ptr_size, 50 | CONVERT_TYPE_UPPER_CASE, 51 | CONVERT_TARGET_ALL, 52 | ) 53 | } 54 | 55 | #[no_mangle] 56 | pub unsafe extern "C" fn to_lower_case_for_utf16( 57 | src_chars_ptr: *const u16, 58 | src_chars_ptr_size: u32, 59 | dst_chars_ptr: *mut u16, 60 | dst_chars_ptr_size: u32, 61 | ) -> u32 { 62 | convert_for_utf16( 63 | src_chars_ptr, 64 | src_chars_ptr_size, 65 | dst_chars_ptr, 66 | dst_chars_ptr_size, 67 | CONVERT_TYPE_LOWER_CASE, 68 | CONVERT_TARGET_ALL, 69 | ) 70 | } 71 | 72 | #[no_mangle] 73 | pub unsafe extern "C" fn to_hiragana_for_utf16( 74 | src_chars_ptr: *const u16, 75 | src_chars_ptr_size: u32, 76 | dst_chars_ptr: *mut u16, 77 | dst_chars_ptr_size: u32, 78 | ) -> u32 { 79 | convert_for_utf16( 80 | src_chars_ptr, 81 | src_chars_ptr_size, 82 | dst_chars_ptr, 83 | dst_chars_ptr_size, 84 | CONVERT_TYPE_HIRAGANA, 85 | CONVERT_TARGET_ALL, 86 | ) 87 | } 88 | 89 | #[no_mangle] 90 | pub unsafe extern "C" fn to_katakana_for_utf16( 91 | src_chars_ptr: *const u16, 92 | src_chars_ptr_size: u32, 93 | dst_chars_ptr: *mut u16, 94 | dst_chars_ptr_size: u32, 95 | ) -> u32 { 96 | convert_for_utf16( 97 | src_chars_ptr, 98 | src_chars_ptr_size, 99 | dst_chars_ptr, 100 | dst_chars_ptr_size, 101 | CONVERT_TYPE_KATAKANA, 102 | CONVERT_TARGET_ALL, 103 | ) 104 | } 105 | 106 | #[no_mangle] 107 | pub unsafe extern "C" fn to_wide_for_utf16( 108 | src_chars_ptr: *const u16, 109 | src_chars_ptr_size: u32, 110 | dst_chars_ptr: *mut u16, 111 | dst_chars_ptr_size: u32, 112 | convert_target: u32, 113 | ) -> u32 { 114 | convert_for_utf16( 115 | src_chars_ptr, 116 | src_chars_ptr_size, 117 | dst_chars_ptr, 118 | dst_chars_ptr_size, 119 | CONVERT_TYPE_WIDE, 120 | convert_target, 121 | ) 122 | } 123 | 124 | #[no_mangle] 125 | pub unsafe extern "C" fn to_narrow_for_utf16( 126 | src_chars_ptr: *const u16, 127 | src_chars_ptr_size: u32, 128 | dst_chars_ptr: *mut u16, 129 | dst_chars_ptr_size: u32, 130 | convert_target: u32, 131 | ) -> u32 { 132 | convert_for_utf16( 133 | src_chars_ptr, 134 | src_chars_ptr_size, 135 | dst_chars_ptr, 136 | dst_chars_ptr_size, 137 | CONVERT_TYPE_NARROW, 138 | convert_target 139 | ) 140 | } 141 | -------------------------------------------------------------------------------- /kanaria_extern/src/utf16/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod converter; 2 | pub mod checker; -------------------------------------------------------------------------------- /kanaria_jvm/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/intellij 3 | # Edit at https://www.gitignore.io/?templates=intellij 4 | 5 | ### Intellij ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 8 | 9 | # User-specific stuff 10 | .idea/**/workspace.xml 11 | .idea/**/tasks.xml 12 | .idea/**/usage.statistics.xml 13 | .idea/**/dictionaries 14 | .idea/**/shelf 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | # When using Gradle or Maven with auto-import, you should exclude module files, 34 | # since they will be recreated, and may cause churn. Uncomment if using 35 | # auto-import. 36 | # .idea/modules.xml 37 | # .idea/*.iml 38 | # .idea/modules 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # Crashlytics plugin (for Android Studio and IntelliJ) 62 | com_crashlytics_export_strings.xml 63 | crashlytics.properties 64 | crashlytics-build.properties 65 | fabric.properties 66 | 67 | # Editor-based Rest Client 68 | .idea/httpRequests 69 | 70 | # Android studio 3.1+ serialized cache file 71 | .idea/caches/build_file_checksums.ser 72 | 73 | # JetBrains templates 74 | **___jb_tmp___ 75 | 76 | ### Intellij Patch ### 77 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 78 | 79 | # *.iml 80 | # modules.xml 81 | # .idea/misc.xml 82 | # *.ipr 83 | 84 | # Sonarlint plugin 85 | .idea/sonarlint 86 | 87 | # End of https://www.gitignore.io/api/intellij 88 | 89 | 90 | /src/main/resources/com/kanaria/platforms/ 91 | *.so 92 | *.dll 93 | -------------------------------------------------------------------------------- /kanaria_jvm/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.nio.file.Files 2 | import java.nio.file.Paths 3 | 4 | plugins { 5 | `maven-publish` 6 | `kotlin-dsl` 7 | id("org.jetbrains.dokka") version "1.9.20" 8 | id("com.osm.gradle.plugins.rustic") version "0.2.7" 9 | } 10 | 11 | val GITHUB_URL = "https://github.com/samunohito/kanaria" 12 | group = "com.kanaria" 13 | version = "0.2.1" 14 | 15 | dependencies { 16 | "implementation"(group = "jaxen", name = "jaxen", version = "2.0.0") 17 | "implementation"(group = "org.dom4j", name = "dom4j", version = "2.1.4") 18 | "testImplementation"(group = "junit", name = "junit", version = "4.13.2") 19 | "testImplementation"(group = "org.jetbrains.kotlin", name = "kotlin-test-junit", version = "2.0.21") 20 | } 21 | 22 | tasks.dokkaHtml { 23 | outputDirectory.set(layout.buildDirectory.dir("javadoc")) 24 | } 25 | 26 | java { 27 | sourceCompatibility = JavaVersion.VERSION_17 28 | targetCompatibility = JavaVersion.VERSION_17 29 | sourceSets { 30 | main { 31 | java.srcDirs("src/main/kotlin") 32 | } 33 | test { 34 | java.srcDirs("src/test/kotlin") 35 | } 36 | } 37 | } 38 | 39 | tasks { 40 | named("javadoc") { 41 | options.locale = "ja_JP" 42 | isFailOnError = false 43 | source = sourceSets["main"].allJava 44 | } 45 | 46 | register("sourcesJar") { 47 | dependsOn(JavaPlugin.CLASSES_TASK_NAME) 48 | archiveClassifier.set("sources") 49 | from(sourceSets["main"].allSource) 50 | } 51 | 52 | register("javadocJar") { 53 | dependsOn(JavaPlugin.JAVADOC_TASK_NAME) 54 | archiveClassifier.set("javadoc") 55 | from(named("javadoc").get().destinationDir) 56 | } 57 | } 58 | 59 | artifacts { 60 | add("archives", tasks["sourcesJar"]) 61 | add("archives", tasks["javadocJar"]) 62 | } 63 | 64 | publishing { 65 | publications { 66 | create("maven") { 67 | pom { 68 | name.set("${project.name}") 69 | description.set("This library provides functions such as hiragana, katakana, half-width and full-width mutual conversion and discrimination.") 70 | url.set(GITHUB_URL) 71 | licenses { 72 | license { 73 | name.set("MIT License") 74 | url.set("https://opensource.org/licenses/MIT") 75 | distribution.set("repo") 76 | } 77 | } 78 | developers { 79 | developer { 80 | id.set("samunohito") 81 | name.set("samunohito") 82 | email.set("46447427+samunohito@users.noreply.github.com") 83 | } 84 | } 85 | scm { 86 | url.set("${GITHUB_URL}.git") 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | val androidNdkPath = "$rootDir/libs/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin" 94 | rustic { 95 | projectSettings.projectLocation("$projectDir/src/main/rust") 96 | defaultConfig.defaultOptions.apply { 97 | jobs(8) 98 | } 99 | 100 | flavors { 101 | create("i686-pc-windows-gnu") { 102 | environments(mapOf( 103 | "AR" to "/usr/bin/i686-w64-mingw32-gcc-ar", 104 | "CC" to "/usr/bin/i686-w64-mingw32-gcc" 105 | )) 106 | defaultOptions.apply { 107 | target("i686-pc-windows-gnu") 108 | cargoConfig.targetTriple.rustFlags(listOf("-C", "panic=abort")) 109 | } 110 | } 111 | 112 | create("x86_64-pc-windows-gnu") { 113 | environments(mapOf( 114 | "AR" to "/usr/bin/x86_64-w64-mingw32-gcc-ar", 115 | "CC" to "/usr/bin/x86_64-w64-mingw32-gcc" 116 | )) 117 | defaultOptions.apply { 118 | target("x86_64-pc-windows-gnu") 119 | } 120 | } 121 | 122 | create("i686-apple-darwin") { 123 | enabled(false) 124 | environments(mapOf( 125 | "AR" to "", 126 | "CC" to "" 127 | )) 128 | defaultOptions.apply { 129 | target("i686-apple-darwin") 130 | } 131 | } 132 | 133 | create("x86_64-apple-darwin") { 134 | enabled(false) 135 | environments(mapOf( 136 | "AR" to "", 137 | "CC" to "" 138 | )) 139 | defaultOptions.apply { 140 | target("x86_64-apple-darwin") 141 | } 142 | } 143 | 144 | create("i686-unknown-linux-gnu") { 145 | environments(mapOf( 146 | "AR" to "/usr/bin/i686-linux-gnu-gcc-ar-12", 147 | "CC" to "/usr/bin/i686-linux-gnu-gcc-12" 148 | )) 149 | defaultOptions.apply { 150 | target("i686-unknown-linux-gnu") 151 | } 152 | } 153 | 154 | create("x86_64-unknown-linux-gnu") { 155 | environments(mapOf( 156 | "AR" to "/usr/bin/x86_64-linux-gnu-gcc-ar-12", 157 | "CC" to "/usr/bin/x86_64-linux-gnu-gcc-12" 158 | )) 159 | defaultOptions.apply { 160 | target("x86_64-unknown-linux-gnu") 161 | } 162 | } 163 | 164 | create("arm-unknown-linux-gnueabihf") { 165 | environments(mapOf( 166 | "AR" to "/usr/bin/arm-linux-gnueabihf-gcc-ar-12", 167 | "CC" to "/usr/bin/arm-linux-gnueabihf-gcc-12" 168 | )) 169 | defaultOptions.apply { 170 | target("arm-unknown-linux-gnueabihf") 171 | } 172 | } 173 | 174 | create("aarch64-unknown-linux-gnu") { 175 | environments(mapOf( 176 | "AR" to "/usr/bin/aarch64-linux-gnu-gcc-ar-12", 177 | "CC" to "/usr/bin/aarch64-linux-gnu-gcc-12" 178 | )) 179 | defaultOptions.apply { 180 | target("aarch64-unknown-linux-gnu") 181 | } 182 | } 183 | 184 | create("i686-linux-android") { 185 | environments(mapOf( 186 | "AR" to "$androidNdkPath/i686-linux-android-ar", 187 | "CC" to "$androidNdkPath/i686-linux-android26-clang" 188 | )) 189 | defaultOptions.apply { 190 | target("i686-linux-android") 191 | } 192 | } 193 | 194 | create("x86_64-linux-android") { 195 | environments(mapOf( 196 | "AR" to "$androidNdkPath/x86_64-linux-android-ar", 197 | "CC" to "$androidNdkPath/x86_64-linux-android26-clang" 198 | )) 199 | defaultOptions.apply { 200 | target("x86_64-linux-android") 201 | } 202 | } 203 | 204 | create("arm-linux-androideabi") { 205 | environments(mapOf( 206 | "AR" to "$androidNdkPath/arm-linux-androideabi-ar", 207 | "CC" to "$androidNdkPath/armv7a-linux-androideabi26-clang" 208 | )) 209 | defaultOptions.apply { 210 | target("arm-linux-androideabi") 211 | } 212 | } 213 | 214 | create("aarch64-linux-android") { 215 | environments(mapOf( 216 | "AR" to "$androidNdkPath/aarch64-linux-android-ar", 217 | "CC" to "$androidNdkPath/aarch64-linux-android26-clang" 218 | )) 219 | defaultOptions.apply { 220 | target("aarch64-linux-android") 221 | } 222 | } 223 | } 224 | 225 | variants.all { 226 | if (enabled == false) { 227 | // 無効化されているvariantは処理しない 228 | return@all 229 | } 230 | 231 | deployReleaseBuildOutput(tasks, this) 232 | } 233 | } 234 | 235 | fun deployReleaseBuildOutput(tasks: TaskContainer, variant: com.osm.gradle.plugins.types.variants.BuildVariant) { 236 | val target = variant.buildOptions.target 237 | val flavor = variant.flavor 238 | val buildTask = tasks["rustBuild${variant.name}"] 239 | if (buildTask == null || target == null || flavor == null) { 240 | println("[${variant.name}] missing parameters.") 241 | return 242 | } 243 | 244 | if (variant.buildOptions.release == false) { 245 | println("[${variant.name}] release build only.") 246 | return 247 | } 248 | 249 | // CCに指定したものをlinkerに流用 250 | flavor.defaultOptions.cargoConfig.targetTriple.linker(variant.environments?.get("CC")) 251 | 252 | // リリースビルドに限り、ビルド成果物をKotlin側ソースのリソースディレクトリに配置する 253 | // また、Android対策として拡張子は省いておく 254 | val srcFilePath = Paths.get("$projectDir/src/main/rust/target/$target/release", getOutputFileName(target)) 255 | val dstFileName = srcFilePath.fileName.toString() 256 | val dstFilePath = Paths.get( 257 | "$projectDir/src/main/resources/com/kanaria/platforms/${target}/", 258 | dstFileName.substring(0, dstFileName.lastIndexOf('.')) 259 | ) 260 | 261 | // variants#all()の実行時点ではビルドが走っておらず成果物がないため、 262 | // ビルドの後処理としてコピー処理を設定する 263 | buildTask.doLast { 264 | if (!Files.exists(dstFilePath.parent)) { 265 | Files.createDirectories(dstFilePath.parent) 266 | } 267 | 268 | if (Files.exists(dstFilePath)) { 269 | Files.delete(dstFilePath) 270 | } 271 | 272 | println("Copy the build output from rustBuild to src/main/resources.") 273 | println(" copy from : $srcFilePath") 274 | println(" copy to : $dstFilePath") 275 | Files.copy(srcFilePath, dstFilePath) 276 | } 277 | } 278 | 279 | fun getOutputFileName(target: String?): String { 280 | return if (target != null && target.contains("windows")) "kanaria_jni.dll" else "libkanaria_jni.so" 281 | } 282 | -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/KanariaLoader.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria 2 | 3 | import com.kanaria.exception.NotLoadingJniException 4 | import com.kanaria.exception.UnsupportedPlatformException 5 | import org.dom4j.Element 6 | import org.dom4j.Node 7 | import org.dom4j.io.SAXReader 8 | import java.io.File 9 | 10 | /** 11 | * 実行中のプラットフォームに適合したdll/soをJVMに読み込む機能を提供します. 12 | */ 13 | object KanariaLoader { 14 | /** 15 | * JNIの読み込みが終了している場合trueになります. 16 | */ 17 | var isLoaded: Boolean = false 18 | private set 19 | 20 | /** 21 | * JNIを読み込んでいるかをチェックします。 22 | * 読み込んでいない場合、例外がスローされます。 23 | * 24 | * @throws NotLoadingJniException [load]メソッドにより初期化処理が呼ばれていないときにスローされます。 25 | */ 26 | internal fun checkOrThrow() { 27 | if (!isLoaded) { 28 | throw NotLoadingJniException("Jni is not loaded. Check if the KanariaLoader#load() function has been executed.") 29 | } 30 | } 31 | 32 | /** 33 | * JNIで使用するライブラリをjarから取り出してカレントディレクトリに配置し、JVMに読み込みます. 34 | */ 35 | fun load() = load(File(".")) 36 | 37 | /** 38 | * JNIで使用するライブラリをjarから取り出して[expandDirectory]で指定されたディレクトリに配置し、JVMに読み込みます. 39 | * @param expandDirectory ライブラリファイルの展開先 40 | */ 41 | fun load(expandDirectory: File) { 42 | if (isLoaded) { 43 | return 44 | } 45 | 46 | val platformName = findCompatiblePlatforms() 47 | val loadPath = expandInternalLibrary(platformName, expandDirectory) 48 | 49 | System.load(loadPath.absolutePath.toString()) 50 | isLoaded = true 51 | } 52 | 53 | /** 54 | * リソースに収められたplatform.xmlからRustのプラットフォームを検索する. 55 | * platform.xmlとは、RustのプラットフォームとJavaの[System.getProperty]から取得できるos.nameとos.archの値等をマッピングしたファイルのこと. 56 | * 57 | * @see System.getProperty 58 | */ 59 | private fun findCompatiblePlatforms(): String { 60 | val inputStream = KanariaLoader.javaClass.getResourceAsStream("platform.xml") 61 | ?: throw RuntimeException("platform.xml is not included.") 62 | val documents = SAXReader().read(inputStream) 63 | val arch = System.getProperty("os.arch") 64 | val os = getFamily() 65 | 66 | val selectOs = documents.selectNodes("/platformMapping/os") 67 | .asNodeSequence() 68 | .filter { 69 | it.attributeValue("name-prefix") 70 | ?.split("|") 71 | ?.any { str -> str.startsWith(os) } ?: false 72 | } 73 | .firstOrNull() ?: throw UnsupportedPlatformException(os, arch) 74 | 75 | val selectArch = selectOs.selectNodes("./arch") 76 | .asNodeSequence() 77 | .filter { 78 | it.attributeValue("type") 79 | ?.split("|") 80 | ?.any { str -> str == arch } ?: false 81 | } 82 | .firstOrNull() ?: throw UnsupportedPlatformException(os, arch) 83 | 84 | val selectPlatforms = selectArch.selectNodes("./platform") 85 | .asNodeSequence() 86 | .toList() 87 | 88 | val targetPlatform = selectPlatforms 89 | .find { platform -> 90 | platform.selectNodes("./java-system-properties") 91 | .asNodeSequence() 92 | .filter { it.attribute("key") != null && it.attribute("value") != null } 93 | .all { System.getProperty(it.attributeValue("key")) == it.attributeValue("value") } 94 | } 95 | ?: selectPlatforms.lastOrNull() 96 | ?: throw UnsupportedPlatformException(os, arch) 97 | 98 | return targetPlatform.attributeValue("name") ?: throw RuntimeException("Impossible") 99 | } 100 | 101 | /** 102 | * Rustのプラットフォームと同じ名前のディレクトリに収められたdll/soをexpandPathの箇所に抽出する. 103 | * それらのディレクトリには、ディレクトリ名と同じプラットフォームを使用してビルドされたdll/soが収められているはず. 104 | * 105 | * @param toolchainName [findCompatiblePlatforms]から取得したRustToolchainの名前 106 | * @param expandPath 展開先ディレクトリ名 107 | * @see findCompatiblePlatforms 108 | */ 109 | private fun expandInternalLibrary(toolchainName: String, expandPath: File): File { 110 | val jniStreamWin = KanariaLoader.javaClass.getResourceAsStream("platforms/$toolchainName/kanaria_jni") 111 | val jniStreamPos = KanariaLoader.javaClass.getResourceAsStream("platforms/$toolchainName/libkanaria_jni") 112 | 113 | val (inputStream, filename) = if (jniStreamWin != null && jniStreamPos == null) { 114 | Pair(jniStreamWin, "kanaria_jni.dll") 115 | } else if (jniStreamWin == null && jniStreamPos != null) { 116 | Pair(jniStreamPos, "libkanaria_jni.so") 117 | } else { 118 | // 1つのディレクトリに両方は置かない 119 | throw RuntimeException("Library placement incorrect.") 120 | } 121 | 122 | val outputFilePath = File(expandPath.toString(), filename) 123 | inputStream.use { 124 | outputFilePath 125 | .outputStream() 126 | .use { outputStream -> 127 | inputStream.copyTo(outputStream) 128 | } 129 | } 130 | 131 | return outputFilePath 132 | } 133 | 134 | private fun getFamily(): String { 135 | val os = System.getProperty("os.name") 136 | return when { 137 | os == null -> "" 138 | os.toLowerCase().startsWith("windows") -> "windows" 139 | os.toLowerCase().startsWith("mac") -> "mac" 140 | os.toLowerCase().startsWith("linux") -> "unix" 141 | else -> "" 142 | } 143 | } 144 | 145 | private fun List.asNodeSequence() = this.asSequence() 146 | .filter { it is Element } 147 | .map { it as Element } 148 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/UcsString.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria 2 | 3 | class UcsString private constructor(arg: String?) { 4 | private var target: String = arg ?: "" 5 | private val requests: ArrayList = ArrayList() 6 | 7 | fun upperCase(): UcsString { 8 | requests.add(RequestParameter(RequestType.UpperCase, CONVERT_TARGET_ALL)) 9 | return this 10 | } 11 | 12 | fun lowerCase(): UcsString { 13 | requests.add(RequestParameter(RequestType.LowerCase, CONVERT_TARGET_ALL)) 14 | return this 15 | } 16 | 17 | fun hiragana(): UcsString { 18 | requests.add(RequestParameter(RequestType.Hiragana, CONVERT_TARGET_ALL)) 19 | return this 20 | } 21 | 22 | fun katakana(): UcsString { 23 | requests.add(RequestParameter(RequestType.Katakana, CONVERT_TARGET_ALL)) 24 | return this 25 | } 26 | 27 | fun wide(target: Int = CONVERT_TARGET_ALL): UcsString { 28 | requests.add(RequestParameter(RequestType.Wide, target)) 29 | return this 30 | } 31 | 32 | fun narrow(target: Int = CONVERT_TARGET_ALL): UcsString { 33 | requests.add(RequestParameter(RequestType.Narrow, target)) 34 | return this 35 | } 36 | 37 | override fun toString(): String { 38 | KanariaLoader.checkOrThrow() 39 | 40 | var tmpBuffer = target 41 | 42 | requests.forEach { 43 | val convertType = it.type; 44 | val convertTarget= it.convertTarget; 45 | val resultLength = if (convertType == RequestType.Narrow) tmpBuffer.length * 2 else tmpBuffer.length 46 | val resultBuffer = CharArray(resultLength + 1) 47 | 48 | val realLength = when (convertType) { 49 | RequestType.UpperCase -> { 50 | toUpperCaseNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength) 51 | } 52 | RequestType.LowerCase -> { 53 | toLowerCaseNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength) 54 | } 55 | RequestType.Hiragana -> { 56 | toHiraganaNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength) 57 | } 58 | RequestType.Katakana -> { 59 | toKatakanaNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength) 60 | } 61 | RequestType.Wide -> { 62 | toWideNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength, convertTarget) 63 | } 64 | RequestType.Narrow -> { 65 | toNarrowNative(tmpBuffer.toCharArray(), tmpBuffer.length, resultBuffer, resultLength, convertTarget) 66 | } 67 | } 68 | 69 | tmpBuffer = String(resultBuffer, 0, realLength) 70 | } 71 | 72 | return tmpBuffer 73 | } 74 | 75 | private external fun convertNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int, convertType: Int, convertTarget: Int): Int 76 | private external fun toUpperCaseNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int): Int 77 | private external fun toLowerCaseNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int): Int 78 | private external fun toHiraganaNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int): Int 79 | private external fun toKatakanaNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int): Int 80 | private external fun toWideNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int, convertTarget: Int): Int 81 | private external fun toNarrowNative(src: CharArray, srcLength: Int, dst: CharArray, dstLength: Int, convertTarget: Int): Int 82 | 83 | companion object { 84 | /** 85 | * 半角・全角の変換対象として数値を設定する際のビットフラグです。 86 | */ 87 | const val CONVERT_TARGET_NUMBER: Int = 0b00000001; 88 | /** 89 | * 半角・全角の変換対象としてアルファベットを設定する際のビットフラグです。 90 | */ 91 | const val CONVERT_TARGET_ALPHABET: Int = 0b00000010; 92 | /** 93 | * 半角・全角の変換対象として記号を設定する際のビットフラグです。 94 | */ 95 | const val CONVERT_TARGET_SYMBOL: Int = 0b00000100; 96 | /** 97 | * 半角・全角の変換対象としてカタカナを設定する際のビットフラグです。 98 | */ 99 | const val CONVERT_TARGET_KATAKANA: Int = 0b00001000; 100 | /** 101 | * 半角・全角の変換が可能なものはすべて変換します。 102 | */ 103 | const val CONVERT_TARGET_ALL: Int = (CONVERT_TARGET_NUMBER or CONVERT_TARGET_ALPHABET or CONVERT_TARGET_SYMBOL or CONVERT_TARGET_KATAKANA); 104 | 105 | fun from(target: String?): UcsString { 106 | return UcsString(target) 107 | } 108 | } 109 | 110 | private enum class RequestType { 111 | UpperCase, LowerCase, Hiragana, Katakana, Wide, Narrow 112 | } 113 | 114 | private class RequestParameter(val type: RequestType, val convertTarget: Int); 115 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/exception/NotLoadingJniException.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria.exception 2 | 3 | class NotLoadingJniException(message: String) : RuntimeException(message) -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/exception/UnsupportedPlatformException.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria.exception 2 | 3 | class UnsupportedPlatformException(val name: String?, val arch: String?) : 4 | RuntimeException("The library for the currently running platform could not be found. [os.name=$name, os.arch=$arch]", null) -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/utils/AsciiUtils.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria.utils 2 | 3 | import com.kanaria.KanariaLoader 4 | 5 | object AsciiUtils { 6 | /** 7 | * ASCII文字かどうかを判定します. 8 | * 9 | * @param target 対象文字列 10 | * @return 判定結果 11 | */ 12 | fun isAscii(target: Char): Boolean { 13 | KanariaLoader.checkOrThrow() 14 | return isAsciiNative(target) 15 | } 16 | 17 | /** 18 | * 半角ASCII文字かどうかを判定します. 19 | * 20 | * @param target 対象文字列 21 | * @return 判定結果 22 | */ 23 | fun isNarrowAscii(target: Char): Boolean { 24 | KanariaLoader.checkOrThrow() 25 | return isNarrowAsciiNative(target) 26 | } 27 | 28 | /** 29 | * 全角ASCII文字かどうかを判定します. 30 | * 31 | * @param target 対象文字列 32 | * @return 判定結果 33 | */ 34 | fun isWideAscii(target: Char): Boolean { 35 | KanariaLoader.checkOrThrow() 36 | return isWideAsciiNative(target) 37 | } 38 | 39 | /** 40 | * 英字の小文字かどうかを判定します. 41 | * 半角・全角は区別しません. 42 | * 43 | * @param target 対象文字列 44 | * @return 判定結果 45 | */ 46 | fun isLowerCase(target: Char): Boolean { 47 | KanariaLoader.checkOrThrow() 48 | return isLowerCaseNative(target) 49 | } 50 | 51 | /** 52 | * 半角英字の小文字かどうかを判定します. 53 | * 54 | * @param target 対象文字列 55 | * @return 判定結果 56 | */ 57 | fun isNarrowLowerCase(target: Char): Boolean { 58 | KanariaLoader.checkOrThrow() 59 | return isNarrowLowerCaseNative(target) 60 | } 61 | 62 | /** 63 | * 全角英字の小文字かどうかを判定します. 64 | * 65 | * @param target 対象文字列 66 | * @return 判定結果 67 | */ 68 | fun isWideLowerCase(target: Char): Boolean { 69 | KanariaLoader.checkOrThrow() 70 | return isWideLowerCaseNative(target) 71 | } 72 | 73 | /** 74 | * 英字の大文字かどうかを判定します. 75 | * 半角・全角は区別しません. 76 | * 77 | * @param target 対象文字列 78 | * @return 判定結果 79 | */ 80 | fun isUpperCase(target: Char): Boolean { 81 | KanariaLoader.checkOrThrow() 82 | return isUpperCaseNative(target) 83 | } 84 | 85 | /** 86 | * 半角英字の大文字かどうかを判定します. 87 | * 88 | * @param target 対象文字列 89 | * @return 判定結果 90 | */ 91 | fun isNarrowUpperCase(target: Char): Boolean { 92 | KanariaLoader.checkOrThrow() 93 | return isNarrowUpperCaseNative(target) 94 | } 95 | 96 | /** 97 | * 全角英字の大文字かどうかを判定します. 98 | * 99 | * @param target 対象文字列 100 | * @return 判定結果 101 | */ 102 | fun isWideUpperCase(target: Char): Boolean { 103 | KanariaLoader.checkOrThrow() 104 | return isWideUpperCaseNative(target) 105 | } 106 | 107 | /** 108 | * 記号かどうかを判定します. 109 | * 半角・全角は区別しません. 110 | * なお、ASCIIコードに属する記号のみを判定します. 111 | * 112 | * @param target 対象文字列 113 | * @return 判定結果 114 | */ 115 | fun isAsciiSymbol(target: Char): Boolean { 116 | KanariaLoader.checkOrThrow() 117 | return isAsciiSymbolNative(target) 118 | } 119 | 120 | /** 121 | * 半角記号かどうかを判定します. 122 | * なお、ASCIIコードに属する記号のみを判定します. 123 | * 124 | * @param target 対象文字列 125 | * @return 判定結果 126 | */ 127 | fun isNarrowAsciiSymbol(target: Char): Boolean { 128 | KanariaLoader.checkOrThrow() 129 | return isNarrowAsciiSymbolNative(target) 130 | } 131 | 132 | /** 133 | * 全角記号かどうかを判定します. 134 | * なお、ASCIIコードに属する記号のみを判定します. 135 | * 136 | * @param target 対象文字列 137 | * @return 判定結果 138 | */ 139 | fun isWideAsciiSymbol(target: Char): Boolean { 140 | KanariaLoader.checkOrThrow() 141 | return isWideAsciiSymbolNative(target) 142 | } 143 | 144 | /** 145 | * 数字かどうかを判定します. 146 | * 半角・全角は区別しません. 147 | * 148 | * @param target 対象文字列 149 | * @return 判定結果 150 | */ 151 | fun isNumber(target: Char): Boolean { 152 | KanariaLoader.checkOrThrow() 153 | return isNumberNative(target) 154 | } 155 | 156 | /** 157 | * 半角数字かどうかを判定します. 158 | * 159 | * @param target 対象文字列 160 | * @return 判定結果 161 | */ 162 | fun isNarrowNumber(target: Char): Boolean { 163 | KanariaLoader.checkOrThrow() 164 | return isNarrowNumberNative(target) 165 | } 166 | 167 | /** 168 | * 全角数字かどうかを判定します. 169 | * 170 | * @param target 対象文字列 171 | * @return 判定結果 172 | */ 173 | fun isWideNumber(target: Char): Boolean { 174 | KanariaLoader.checkOrThrow() 175 | return isWideNumberNative(target) 176 | } 177 | 178 | /** 179 | * 小文字を大文字に変換します. 180 | * 半角・全角は区別しません. 181 | * 182 | * @param target 対象文字列 183 | * @return 変換後文字 184 | */ 185 | fun convertToUpperCase(target: Char): Char { 186 | KanariaLoader.checkOrThrow() 187 | return convertToUpperCaseNative(target) 188 | } 189 | 190 | /** 191 | * 大文字を小文字に変換します. 192 | * 半角・全角は区別しません. 193 | * 194 | * @param target 対象文字列 195 | * @return 変換後文字 196 | */ 197 | fun convertToLowerCase(target: Char): Char { 198 | KanariaLoader.checkOrThrow() 199 | return convertToLowerCaseNative(target) 200 | } 201 | 202 | private external fun isAsciiNative(target: Char): Boolean 203 | private external fun isNarrowAsciiNative(target: Char): Boolean 204 | private external fun isWideAsciiNative(target: Char): Boolean 205 | private external fun isLowerCaseNative(target: Char): Boolean 206 | private external fun isNarrowLowerCaseNative(target: Char): Boolean 207 | private external fun isWideLowerCaseNative(target: Char): Boolean 208 | private external fun isUpperCaseNative(target: Char): Boolean 209 | private external fun isNarrowUpperCaseNative(target: Char): Boolean 210 | private external fun isWideUpperCaseNative(target: Char): Boolean 211 | private external fun isAsciiSymbolNative(target: Char): Boolean 212 | private external fun isNarrowAsciiSymbolNative(target: Char): Boolean 213 | private external fun isWideAsciiSymbolNative(target: Char): Boolean 214 | private external fun isNumberNative(target: Char): Boolean 215 | private external fun isNarrowNumberNative(target: Char): Boolean 216 | private external fun isWideNumberNative(target: Char): Boolean 217 | private external fun convertToUpperCaseNative(target: Char): Char 218 | private external fun convertToLowerCaseNative(target: Char): Char 219 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/utils/KanaUtils.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria.utils 2 | 3 | import com.kanaria.KanariaLoader 4 | 5 | object KanaUtils { 6 | /** 7 | * 対象がひらがなかどうかを判定します. 8 | * 9 | * @param target 対象文字列 10 | * @return 判定結果 11 | */ 12 | fun isHiragana(target: Char): Boolean { 13 | KanariaLoader.checkOrThrow() 14 | return isHiraganaNative(target) 15 | } 16 | 17 | /** 18 | * 対象がカタカナかどうかを判定します. 19 | * 半角・全角は区別しません. 20 | * 21 | * @param target 対象文字列 22 | * @return 判定結果 23 | */ 24 | fun isKatakana(target: Char): Boolean { 25 | KanariaLoader.checkOrThrow() 26 | return isKatakanaNative(target) 27 | } 28 | 29 | /** 30 | * 対象が半角カタカナかどうかを判定します. 31 | * 32 | * @param target 対象文字列 33 | * @return 判定結果 34 | */ 35 | fun isNarrowKatakana(target: Char): Boolean { 36 | KanariaLoader.checkOrThrow() 37 | return isNarrowKatakanaNative(target) 38 | } 39 | 40 | /** 41 | * 対象が全角カタカナかどうかを判定します. 42 | * 43 | * @param target 対象文字列 44 | * @return 判定結果 45 | */ 46 | fun isWideKatakana(target: Char): Boolean { 47 | KanariaLoader.checkOrThrow() 48 | return isWideKatakanaNative(target) 49 | } 50 | 51 | /** 52 | * 対象が半角記号かどうかを判定します. 53 | * ASCIIコード内の記号はtrueになりません. 54 | * 55 | * @param target 対象文字列 56 | * @return 判定結果 57 | */ 58 | fun isJisSymbol(target: Char): Boolean { 59 | KanariaLoader.checkOrThrow() 60 | return isJisSymbolNative(target) 61 | } 62 | 63 | /** 64 | * 対象が半角記号かどうかを判定します. 65 | * ASCIIコード内の記号はtrueになりません. 66 | * 67 | * @param target 対象文字列 68 | * @return 判定結果 69 | */ 70 | fun isNarrowJisSymbol(target: Char): Boolean { 71 | KanariaLoader.checkOrThrow() 72 | return isNarrowJisSymbolNative(target) 73 | } 74 | 75 | /** 76 | * 対象が全角記号かどうかを判定します. 77 | * ASCIIコード内の記号はtrueになりません. 78 | * 79 | * @param target 対象文字列 80 | * @return 判定結果 81 | */ 82 | fun isWideJisSymbol(target: Char): Boolean { 83 | KanariaLoader.checkOrThrow() 84 | return isWideJisSymbolNative(target) 85 | } 86 | 87 | /** 88 | * ひらがなに変換可能な全角カタカナかどうかを判定します. 89 | * 90 | * @param target 対象文字列 91 | * @return 変換後文字 92 | */ 93 | fun isCanConvertHiragana(target: Char): Boolean { 94 | KanariaLoader.checkOrThrow() 95 | return isCanConvertHiraganaNative(target) 96 | } 97 | 98 | /** 99 | * 全角カタカナをひらがなに変換します. 100 | * 101 | * @param target 対象文字列 102 | * @return 変換後文字 103 | */ 104 | fun convertToHiragana(target: Char): Char { 105 | KanariaLoader.checkOrThrow() 106 | return convertToHiraganaNative(target) 107 | } 108 | 109 | /** 110 | * ひらがなを全角カタカナに変換します. 111 | * 112 | * @param target 対象文字列 113 | * @return 変換後文字 114 | */ 115 | fun convertToKatakana(target: Char): Char { 116 | KanariaLoader.checkOrThrow() 117 | return convertToKatakanaNative(target) 118 | } 119 | 120 | private external fun isHiraganaNative(target: Char): Boolean 121 | private external fun isKatakanaNative(target: Char): Boolean 122 | private external fun isNarrowKatakanaNative(target: Char): Boolean 123 | private external fun isWideKatakanaNative(target: Char): Boolean 124 | private external fun isJisSymbolNative(target: Char): Boolean 125 | private external fun isNarrowJisSymbolNative(target: Char): Boolean 126 | private external fun isWideJisSymbolNative(target: Char): Boolean 127 | private external fun isCanConvertHiraganaNative(target: Char): Boolean 128 | private external fun convertToHiraganaNative(target: Char): Char 129 | private external fun convertToKatakanaNative(target: Char): Char 130 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/kotlin/com/kanaria/utils/WidthUtils.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria.utils 2 | 3 | import com.kanaria.KanariaLoader 4 | 5 | object WidthUtils { 6 | private external fun convertToWideNative(target: Char, next: Char, isPad: BooleanArray): Char 7 | private external fun convertToNarrowNative(target: Char, outChar: CharArray): Char 8 | 9 | /** 10 | * 全角文字を半角に変換します。 11 | * 一文字目と二文字目が結合可能だった場合、結合済みの文字列を返却します。 12 | * 文字列が結合された場合、2つ目の戻り値にtrueが入っています。 13 | * 14 | * @param target 対象文字 15 | * @param next 対象文字の次の文字 16 | * @result 処理結果クラス 17 | * @see [ConvertToWideResult] 18 | */ 19 | fun convertToWide(target: Char, next: Char): ConvertToWideResult { 20 | KanariaLoader.checkOrThrow() 21 | 22 | val isPad = BooleanArray(1) 23 | val result = convertToWideNative(target, next, isPad) 24 | 25 | return ConvertToWideResult(result, isPad[0]) 26 | } 27 | 28 | /** 29 | * 全角文字を半角に変換します。 30 | * 31 | * @param target 対象文字 32 | * @result 処理結果クラス 33 | * @see [ConvertToNarrowResult] 34 | */ 35 | fun convertToNarrow(target: Char): ConvertToNarrowResult { 36 | KanariaLoader.checkOrThrow() 37 | 38 | val next = CharArray(1) 39 | val result = convertToNarrowNative(target, next) 40 | 41 | return ConvertToNarrowResult(result, if (next[0] == 0.toChar()) null else next[0]) 42 | } 43 | 44 | /** 45 | * [WidthUtils.convertToWide]の戻り値を格納します. 46 | * 変換対象文字の次の文字が濁音・半濁音であり、 47 | * なおかつ変換対象文字と結合可能だった場合(=1文字の濁音・半濁音文字がある場合)、 48 | * 結合後の文字が[result]にセットされます. 49 | * 50 | * - [result] 51 | * 変換後文字を格納します. 52 | * - [isPadding] 53 | * 結合を行った場合trueになります. 54 | */ 55 | class ConvertToWideResult(val result: Char, val isPadding: Boolean) 56 | 57 | /** 58 | * [WidthUtils.convertToNarrow]の戻り値を格納します. 59 | * - [first] 60 | * 変換後文字の1文字目を保持します. 61 | * - [second] 62 | * 変換後文字の2文字目を保持します. 63 | * 変換対象文字が濁音・半濁音だった場合、半角の濁音・半濁音記号が設定されます. 64 | * 静音など、変換後文字が1文字の場合はnullが設定されます. 65 | */ 66 | class ConvertToNarrowResult(val first: Char, val second: Char?) 67 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/resources/com/kanaria/platform.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 14 | 15 | 16 | 17 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.i686-pc-windows-gnu] 2 | linker = "/usr/bin/i686-w64-mingw32-gcc" 3 | 4 | [target.x86_64-pc-windows-gnu] 5 | linker = "/usr/bin/x86_64-w64-mingw32-gcc" 6 | 7 | [target.i686-apple-darwin] 8 | linker = "/usr/bin/i686-linux-gnu-gcc-12" 9 | 10 | [target.x86_64-apple-darwin] 11 | linker = "/usr/bin/x86_64-linux-gnu-gcc-12" 12 | 13 | [target.armv7-apple-ios] 14 | linker = "/usr/bin/arm-linux-gnueabihf-gcc-12" 15 | 16 | [target.aarch64-apple-ios] 17 | linker = "/usr/bin/aarch64-linux-gnu-gcc-12" 18 | 19 | [target.i686-unknown-linux-gnu] 20 | linker = "/usr/bin/i686-linux-gnu-gcc-12" 21 | 22 | [target.x86_64-unknown-linux-gnu] 23 | linker = "/usr/bin/x86_64-linux-gnu-gcc-12" 24 | 25 | [target.arm-unknown-linux-gnueabihf] 26 | linker = "/usr/bin/arm-linux-gnueabihf-gcc-12" 27 | 28 | [target.aarch64-unknown-linux-gnu] 29 | linker = "/usr/bin/aarch64-linux-gnu-gcc-12" 30 | 31 | [target.i686-linux-android] 32 | linker = "/usr/local/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android33-clang" 33 | 34 | [target.x86_64-linux-android] 35 | linker = "/usr/local/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android33-clang" 36 | 37 | [target.armv7-linux-androideabi] 38 | linker = "/usr/local/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi33-clang" 39 | 40 | [target.aarch64-linux-android] 41 | linker = "/usr/local/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang" 42 | -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/rust 2 | # Edit at https://www.gitignore.io/?templates=rust 3 | 4 | ### Rust ### 5 | # Generated by Cargo 6 | # will have compiled files and executables 7 | /target/ 8 | 9 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 10 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 11 | Cargo.lock 12 | 13 | # These are backup files generated by rustfmt 14 | **/*.rs.bk 15 | 16 | # End of https://www.gitignore.io/api/rust 17 | 18 | AndroidNDK/* -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kanaria_jni" 3 | version = "0.1.0" 4 | authors = ["samunohito <46447427+samunohito@users.noreply.github.com>"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | kanaria = { path = "../../../../kanaria_core" } 9 | jni = "0.14.0" 10 | 11 | [lib] 12 | name = "kanaria_jni" 13 | path = "src/lib.rs" 14 | crate-type = ["cdylib"] 15 | -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/src/checker.rs: -------------------------------------------------------------------------------- 1 | extern crate jni; 2 | extern crate kanaria; 3 | 4 | use std::slice::from_raw_parts; 5 | 6 | use jni::JNIEnv; 7 | use jni::sys::*; 8 | 9 | use kanaria::utils::{AsciiUtils, KanaUtils, WidthUtils}; 10 | 11 | #[no_mangle] 12 | #[allow(unused_variables, non_snake_case)] 13 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isAsciiNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 14 | AsciiUtils::is_ascii(target) as jboolean 15 | } 16 | 17 | #[no_mangle] 18 | #[allow(unused_variables, non_snake_case)] 19 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNarrowAsciiNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 20 | AsciiUtils::is_narrow_ascii(target) as jboolean 21 | } 22 | 23 | #[no_mangle] 24 | #[allow(unused_variables, non_snake_case)] 25 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isWideAsciiNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 26 | AsciiUtils::is_wide_ascii(target) as jboolean 27 | } 28 | 29 | #[no_mangle] 30 | #[allow(unused_variables, non_snake_case)] 31 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isLowerCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 32 | AsciiUtils::is_lower_case(target) as jboolean 33 | } 34 | 35 | #[no_mangle] 36 | #[allow(unused_variables, non_snake_case)] 37 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNarrowLowerCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 38 | AsciiUtils::is_narrow_lower_case(target) as jboolean 39 | } 40 | 41 | #[no_mangle] 42 | #[allow(unused_variables, non_snake_case)] 43 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isWideLowerCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 44 | AsciiUtils::is_wide_lower_case(target) as jboolean 45 | } 46 | 47 | #[no_mangle] 48 | #[allow(unused_variables, non_snake_case)] 49 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isUpperCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 50 | AsciiUtils::is_upper_case(target) as jboolean 51 | } 52 | 53 | #[no_mangle] 54 | #[allow(unused_variables, non_snake_case)] 55 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNarrowUpperCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 56 | AsciiUtils::is_narrow_upper_case(target) as jboolean 57 | } 58 | 59 | #[no_mangle] 60 | #[allow(unused_variables, non_snake_case)] 61 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isWideUpperCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 62 | AsciiUtils::is_wide_upper_case(target) as jboolean 63 | } 64 | 65 | #[no_mangle] 66 | #[allow(unused_variables, non_snake_case)] 67 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isAsciiSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 68 | AsciiUtils::is_ascii_symbol(target) as jboolean 69 | } 70 | 71 | #[no_mangle] 72 | #[allow(unused_variables, non_snake_case)] 73 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNarrowAsciiSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 74 | AsciiUtils::is_narrow_ascii_symbol(target) as jboolean 75 | } 76 | 77 | #[no_mangle] 78 | #[allow(unused_variables, non_snake_case)] 79 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isWideAsciiSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 80 | AsciiUtils::is_wide_ascii_symbol(target) as jboolean 81 | } 82 | 83 | #[no_mangle] 84 | #[allow(unused_variables, non_snake_case)] 85 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNumberNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 86 | AsciiUtils::is_number(target) as jboolean 87 | } 88 | 89 | #[no_mangle] 90 | #[allow(unused_variables, non_snake_case)] 91 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isNarrowNumberNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 92 | AsciiUtils::is_narrow_number(target) as jboolean 93 | } 94 | 95 | #[no_mangle] 96 | #[allow(unused_variables, non_snake_case)] 97 | pub extern fn Java_com_kanaria_utils_AsciiUtils_isWideNumberNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 98 | AsciiUtils::is_wide_number(target) as jboolean 99 | } 100 | 101 | #[no_mangle] 102 | #[allow(unused_variables, non_snake_case)] 103 | pub extern fn Java_com_kanaria_utils_AsciiUtils_convertToUpperCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jchar { 104 | AsciiUtils::convert_to_upper_case(target) as jchar 105 | } 106 | 107 | #[no_mangle] 108 | #[allow(unused_variables, non_snake_case)] 109 | pub extern fn Java_com_kanaria_utils_AsciiUtils_convertToLowerCaseNative(env: JNIEnv, class: jclass, target: jchar) -> jchar { 110 | AsciiUtils::convert_to_lower_case(target) as jchar 111 | } 112 | 113 | 114 | #[no_mangle] 115 | #[allow(unused_variables, non_snake_case)] 116 | pub extern fn Java_com_kanaria_utils_KanaUtils_isHiraganaNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 117 | KanaUtils::is_hiragana(target) as jboolean 118 | } 119 | 120 | #[no_mangle] 121 | #[allow(unused_variables, non_snake_case)] 122 | pub extern fn Java_com_kanaria_utils_KanaUtils_isKatakanaNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 123 | KanaUtils::is_katakana(target) as jboolean 124 | } 125 | 126 | #[no_mangle] 127 | #[allow(unused_variables, non_snake_case)] 128 | pub extern fn Java_com_kanaria_utils_KanaUtils_isNarrowKatakanaNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 129 | KanaUtils::is_narrow_katakana(target) as jboolean 130 | } 131 | 132 | #[no_mangle] 133 | #[allow(unused_variables, non_snake_case)] 134 | pub extern fn Java_com_kanaria_utils_KanaUtils_isWideKatakanaNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 135 | KanaUtils::is_wide_katakana(target) as jboolean 136 | } 137 | 138 | #[no_mangle] 139 | #[allow(unused_variables, non_snake_case)] 140 | pub extern fn Java_com_kanaria_utils_KanaUtils_isJisSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 141 | KanaUtils::is_jis_symbol(target) as jboolean 142 | } 143 | 144 | #[no_mangle] 145 | #[allow(unused_variables, non_snake_case)] 146 | pub extern fn Java_com_kanaria_utils_KanaUtils_isNarrowJisSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 147 | KanaUtils::is_narrow_jis_symbol(target) as jboolean 148 | } 149 | 150 | #[no_mangle] 151 | #[allow(unused_variables, non_snake_case)] 152 | pub extern fn Java_com_kanaria_utils_KanaUtils_isWideJisSymbolNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 153 | KanaUtils::is_wide_jis_symbol(target) as jboolean 154 | } 155 | 156 | #[no_mangle] 157 | #[allow(unused_variables, non_snake_case)] 158 | pub extern fn Java_com_kanaria_utils_KanaUtils_isCanConvertHiraganaNative(env: JNIEnv, class: jclass, target: jchar) -> jboolean { 159 | KanaUtils::is_can_convert_hiragana(target) as jboolean 160 | } 161 | 162 | #[no_mangle] 163 | #[allow(unused_variables, non_snake_case)] 164 | pub extern fn Java_com_kanaria_utils_KanaUtils_convertToHiraganaNative(env: JNIEnv, class: jclass, target: jchar) -> jchar { 165 | KanaUtils::convert_to_hiragana(target) as jchar 166 | } 167 | 168 | #[no_mangle] 169 | #[allow(unused_variables, non_snake_case)] 170 | pub extern fn Java_com_kanaria_utils_KanaUtils_convertToKatakanaNative(env: JNIEnv, class: jclass, target: jchar) -> jchar { 171 | KanaUtils::convert_to_katakana(target) as jchar 172 | } 173 | 174 | 175 | #[no_mangle] 176 | #[allow(unused_variables, non_snake_case)] 177 | pub unsafe extern fn Java_com_kanaria_utils_WidthUtils_convertToWideNative(env: JNIEnv, class: jclass, target: jchar, next: jchar, is_pad: jbooleanArray) -> jchar { 178 | let (result_ret, is_pad_ret) = WidthUtils::convert_to_wide(target, next); 179 | let _ = env.set_boolean_array_region(is_pad, 0, from_raw_parts(&(is_pad_ret as u8) as *const jboolean, 1)); 180 | return result_ret as jchar; 181 | } 182 | 183 | #[no_mangle] 184 | #[allow(unused_variables, non_snake_case)] 185 | pub unsafe extern fn Java_com_kanaria_utils_WidthUtils_convertToNarrowNative(env: JNIEnv, class: jclass, target: jchar, out_char: jcharArray) -> jchar { 186 | let (first, second) = WidthUtils::convert_to_narrow(target); 187 | let _ = env.set_char_array_region(out_char, 0, from_raw_parts(&(second as u16) as *const jchar, 1)); 188 | return first as jchar; 189 | } -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/src/converter.rs: -------------------------------------------------------------------------------- 1 | extern crate jni; 2 | extern crate kanaria; 3 | 4 | use jni::JNIEnv; 5 | use jni::sys::*; 6 | 7 | use kanaria::constants::*; 8 | use kanaria::string::ConvertType; 9 | use kanaria::string::ConvertType::{Hiragana, Katakana, LowerCase, Narrow, UpperCase, Wide}; 10 | use kanaria::string::UCSStr; 11 | use kanaria::utils::ConvertTarget; 12 | 13 | fn int_to_convert_type(convert_type: u32) -> ConvertType { 14 | match convert_type { 15 | CONVERT_TYPE_UPPER_CASE => UpperCase, 16 | CONVERT_TYPE_LOWER_CASE => LowerCase, 17 | CONVERT_TYPE_HIRAGANA => Hiragana, 18 | CONVERT_TYPE_KATAKANA => Katakana, 19 | CONVERT_TYPE_NARROW => Narrow, 20 | CONVERT_TYPE_WIDE => Wide, 21 | _ => ConvertType::None, 22 | } 23 | } 24 | 25 | #[no_mangle] 26 | #[allow(unused_variables, non_snake_case)] 27 | pub unsafe extern fn Java_com_kanaria_UcsString_convertNative( 28 | env: JNIEnv, 29 | class: jclass, 30 | src_chars: jcharArray, 31 | src_chars_len: jint, 32 | dst_chars: jcharArray, 33 | dst_chars_len: jint, 34 | convert_type: jint, 35 | convert_target: jint, 36 | ) -> jint { 37 | // 処理対象文字列の取得 38 | let mut src_buffer = Vec::::with_capacity(src_chars_len as usize); 39 | src_buffer.set_len(src_chars_len as usize); 40 | let _ = env.get_char_array_region(src_chars, 0, src_buffer.as_mut()); 41 | 42 | // 処理後文字列の領域確保 43 | let mut dst_buffer = Vec::with_capacity(dst_chars_len as usize); 44 | dst_buffer.set_len(dst_chars_len as usize); 45 | 46 | // 変換処理 47 | let size = UCSStr::convert_raw( 48 | src_buffer.as_ptr(), 49 | dst_buffer.as_mut_ptr(), 50 | src_chars_len as usize, 51 | int_to_convert_type(convert_type as u32), 52 | ConvertTarget::from_bits(convert_target as u32).unwrap_or(ConvertTarget::ALL), 53 | ) as u32; 54 | dst_buffer.set_len(size as usize); 55 | 56 | // 処理後文字列の返却処理 57 | let _ = env.set_char_array_region(dst_chars, 0, dst_buffer.as_slice()); 58 | 59 | return dst_buffer.len() as jint; 60 | } 61 | 62 | #[no_mangle] 63 | #[allow(unused_variables, non_snake_case)] 64 | pub unsafe extern fn Java_com_kanaria_UcsString_toUpperCaseNative( 65 | env: JNIEnv, 66 | class: jclass, 67 | src_chars: jcharArray, 68 | src_chars_len: jint, 69 | dst_chars: jcharArray, 70 | dst_chars_len: jint, 71 | ) -> jint { 72 | Java_com_kanaria_UcsString_convertNative( 73 | env, 74 | class, 75 | src_chars, 76 | src_chars_len, 77 | dst_chars, 78 | dst_chars_len, 79 | CONVERT_TYPE_UPPER_CASE as jint, 80 | CONVERT_TARGET_ALL as jint, 81 | ) 82 | } 83 | 84 | #[no_mangle] 85 | #[allow(unused_variables, non_snake_case)] 86 | pub unsafe extern fn Java_com_kanaria_UcsString_toLowerCaseNative( 87 | env: JNIEnv, 88 | class: jclass, 89 | src_chars: jcharArray, 90 | src_chars_len: jint, 91 | dst_chars: jcharArray, 92 | dst_chars_len: jint, 93 | ) -> jint { 94 | Java_com_kanaria_UcsString_convertNative( 95 | env, 96 | class, 97 | src_chars, 98 | src_chars_len, 99 | dst_chars, 100 | dst_chars_len, 101 | CONVERT_TYPE_LOWER_CASE as jint, 102 | CONVERT_TARGET_ALL as jint, 103 | ) 104 | } 105 | 106 | #[no_mangle] 107 | #[allow(unused_variables, non_snake_case)] 108 | pub unsafe extern fn Java_com_kanaria_UcsString_toHiraganaNative( 109 | env: JNIEnv, 110 | class: jclass, 111 | src_chars: jcharArray, 112 | src_chars_len: jint, 113 | dst_chars: jcharArray, 114 | dst_chars_len: jint, 115 | ) -> jint { 116 | Java_com_kanaria_UcsString_convertNative( 117 | env, 118 | class, 119 | src_chars, 120 | src_chars_len, 121 | dst_chars, 122 | dst_chars_len, 123 | CONVERT_TYPE_HIRAGANA as jint, 124 | CONVERT_TARGET_ALL as jint, 125 | ) 126 | } 127 | 128 | #[no_mangle] 129 | #[allow(unused_variables, non_snake_case)] 130 | pub unsafe extern fn Java_com_kanaria_UcsString_toKatakanaNative( 131 | env: JNIEnv, 132 | class: jclass, 133 | src_chars: jcharArray, 134 | src_chars_len: jint, 135 | dst_chars: jcharArray, 136 | dst_chars_len: jint, 137 | ) -> jint { 138 | Java_com_kanaria_UcsString_convertNative( 139 | env, 140 | class, 141 | src_chars, 142 | src_chars_len, 143 | dst_chars, 144 | dst_chars_len, 145 | CONVERT_TYPE_KATAKANA as jint, 146 | CONVERT_TARGET_ALL as jint, 147 | ) 148 | } 149 | 150 | #[no_mangle] 151 | #[allow(unused_variables, non_snake_case)] 152 | pub unsafe extern fn Java_com_kanaria_UcsString_toWideNative( 153 | env: JNIEnv, 154 | class: jclass, 155 | src_chars: jcharArray, 156 | src_chars_len: jint, 157 | dst_chars: jcharArray, 158 | dst_chars_len: jint, 159 | convert_target: jint, 160 | ) -> jint { 161 | Java_com_kanaria_UcsString_convertNative( 162 | env, 163 | class, 164 | src_chars, 165 | src_chars_len, 166 | dst_chars, 167 | dst_chars_len, 168 | CONVERT_TYPE_WIDE as jint, 169 | convert_target, 170 | ) 171 | } 172 | 173 | #[no_mangle] 174 | #[allow(unused_variables, non_snake_case)] 175 | pub unsafe extern fn Java_com_kanaria_UcsString_toNarrowNative( 176 | env: JNIEnv, 177 | class: jclass, 178 | src_chars: jcharArray, 179 | src_chars_len: jint, 180 | dst_chars: jcharArray, 181 | dst_chars_len: jint, 182 | convert_target: jint, 183 | ) -> jint { 184 | Java_com_kanaria_UcsString_convertNative( 185 | env, 186 | class, 187 | src_chars, 188 | src_chars_len, 189 | dst_chars, 190 | dst_chars_len, 191 | CONVERT_TYPE_NARROW as jint, 192 | convert_target, 193 | ) 194 | } 195 | -------------------------------------------------------------------------------- /kanaria_jvm/src/main/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod checker; 2 | pub mod converter; -------------------------------------------------------------------------------- /kanaria_jvm/src/test/kotlin/com/kanaria/ExampleSentenceTest.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria 2 | 3 | import com.kanaria.utils.AsciiUtils 4 | import com.kanaria.utils.KanaUtils 5 | import com.kanaria.utils.WidthUtils 6 | import org.junit.Assert 7 | import org.junit.Before 8 | import org.junit.Test 9 | import java.nio.file.Files 10 | import java.nio.file.Paths 11 | 12 | class ExampleSentenceTest { 13 | @Test 14 | fun exampleSentence1() { 15 | val hankaku = "チタタプ トテトテFoooo!!!11!" 16 | val zenkaku = "チタタプ トテトテFoooo!!!11!" 17 | 18 | KanariaLoader.load() 19 | Assert.assertEquals(hankaku, UcsString.from(zenkaku).narrow().toString()) 20 | Assert.assertEquals(zenkaku, UcsString.from(hankaku).wide().toString()) 21 | } 22 | 23 | @Test 24 | fun exampleSentence2() { 25 | val hankaku = "吾輩ハ😺猫デアル😺" 26 | val zenkaku = "吾輩ハ😺猫デアル😺" 27 | 28 | KanariaLoader.load() 29 | Assert.assertEquals(hankaku, UcsString.from(zenkaku).narrow().toString()) 30 | Assert.assertEquals(zenkaku, UcsString.from(hankaku).wide().toString()) 31 | } 32 | 33 | @Test 34 | fun exampleSentence3() { 35 | val hankaku = "フジサンコポォ" 36 | val zenkaku = "フジサンコポォ" 37 | 38 | KanariaLoader.load() 39 | Assert.assertEquals(hankaku, UcsString.from(zenkaku).narrow().toString()) 40 | Assert.assertEquals(zenkaku, UcsString.from(hankaku).wide().toString()) 41 | } 42 | 43 | @Test 44 | fun exampleSentence4() { 45 | val katakana = "チタタプ トテトテ" 46 | val hiragana = "ちたたぷ とてとて" 47 | 48 | KanariaLoader.load() 49 | Assert.assertEquals(katakana, UcsString.from(hiragana).katakana().toString()) 50 | Assert.assertEquals(hiragana, UcsString.from(katakana).hiragana().toString()) 51 | } 52 | 53 | @Test 54 | fun exampleSentence5() { 55 | val katakana = "吾輩ハ😺猫デアル😺" 56 | val hiragana = "吾輩は😺猫である😺" 57 | 58 | KanariaLoader.load() 59 | Assert.assertEquals(katakana, UcsString.from(hiragana).katakana().toString()) 60 | Assert.assertEquals(hiragana, UcsString.from(katakana).hiragana().toString()) 61 | } 62 | 63 | @Test 64 | fun exampleSentence6() { 65 | KanariaLoader.load() 66 | 67 | Assert.assertTrue(AsciiUtils.isAscii('a')) 68 | Assert.assertTrue(AsciiUtils.isWideAscii('w')) 69 | Assert.assertTrue(AsciiUtils.isNarrowAscii('n')) 70 | Assert.assertFalse(AsciiUtils.isAscii('あ')) 71 | Assert.assertFalse(AsciiUtils.isWideAscii('漢')) 72 | Assert.assertFalse(AsciiUtils.isNarrowAscii('ア')) 73 | 74 | Assert.assertTrue(AsciiUtils.isLowerCase('a')) 75 | Assert.assertTrue(AsciiUtils.isWideLowerCase('w')) 76 | Assert.assertTrue(AsciiUtils.isNarrowLowerCase('n')) 77 | Assert.assertFalse(AsciiUtils.isLowerCase('A')) 78 | Assert.assertFalse(AsciiUtils.isWideLowerCase('n')) 79 | Assert.assertFalse(AsciiUtils.isNarrowLowerCase('w')) 80 | 81 | Assert.assertTrue(AsciiUtils.isUpperCase('A')) 82 | Assert.assertTrue(AsciiUtils.isWideUpperCase('W')) 83 | Assert.assertTrue(AsciiUtils.isNarrowUpperCase('N')) 84 | Assert.assertFalse(AsciiUtils.isUpperCase('a')) 85 | Assert.assertFalse(AsciiUtils.isWideUpperCase('w')) 86 | Assert.assertFalse(AsciiUtils.isNarrowUpperCase('n')) 87 | 88 | Assert.assertTrue(AsciiUtils.isAsciiSymbol('*')) 89 | Assert.assertTrue(AsciiUtils.isWideAsciiSymbol('@')) 90 | Assert.assertTrue(AsciiUtils.isNarrowAsciiSymbol('@')) 91 | Assert.assertFalse(AsciiUtils.isAsciiSymbol('、')) 92 | Assert.assertFalse(AsciiUtils.isWideAsciiSymbol('@')) 93 | Assert.assertFalse(AsciiUtils.isNarrowAsciiSymbol('@')) 94 | 95 | Assert.assertTrue(AsciiUtils.isNumber('0')) 96 | Assert.assertTrue(AsciiUtils.isWideNumber('0')) 97 | Assert.assertTrue(AsciiUtils.isNarrowNumber('1')) 98 | Assert.assertFalse(AsciiUtils.isNumber('a')) 99 | Assert.assertFalse(AsciiUtils.isWideNumber('1')) 100 | Assert.assertFalse(AsciiUtils.isNarrowNumber('0')) 101 | 102 | Assert.assertEquals('a', AsciiUtils.convertToLowerCase('A')) 103 | Assert.assertEquals('A', AsciiUtils.convertToUpperCase('a')) 104 | Assert.assertEquals('あ', AsciiUtils.convertToLowerCase('あ')) 105 | Assert.assertEquals('0', AsciiUtils.convertToUpperCase('0')) 106 | } 107 | 108 | @Test 109 | fun exampleSentence7() { 110 | KanariaLoader.load() 111 | 112 | Assert.assertTrue(KanaUtils.isHiragana('あ')) 113 | Assert.assertFalse(KanaUtils.isHiragana('ア')) 114 | 115 | Assert.assertTrue(KanaUtils.isKatakana('ア')) 116 | Assert.assertTrue(KanaUtils.isWideKatakana('カ')) 117 | Assert.assertTrue(KanaUtils.isNarrowKatakana('サ')) 118 | Assert.assertFalse(KanaUtils.isKatakana('あ')) 119 | Assert.assertFalse(KanaUtils.isWideKatakana('カ')) 120 | Assert.assertFalse(KanaUtils.isNarrowKatakana('サ')) 121 | 122 | Assert.assertTrue(KanaUtils.isJisSymbol('ゟ')) 123 | Assert.assertTrue(KanaUtils.isWideJisSymbol('・')) 124 | Assert.assertTrue(KanaUtils.isNarrowJisSymbol('・')) 125 | Assert.assertFalse(KanaUtils.isJisSymbol('@')) 126 | Assert.assertFalse(KanaUtils.isWideJisSymbol('・')) 127 | Assert.assertFalse(KanaUtils.isNarrowJisSymbol('・')) 128 | 129 | Assert.assertTrue(KanaUtils.isCanConvertHiragana('ワ')) 130 | Assert.assertFalse(KanaUtils.isCanConvertHiragana('ヷ')) 131 | 132 | Assert.assertEquals('あ', KanaUtils.convertToHiragana('ア')) 133 | Assert.assertEquals('ア', KanaUtils.convertToKatakana('あ')) 134 | Assert.assertEquals('ア', KanaUtils.convertToHiragana('ア')) 135 | Assert.assertEquals('漢', KanaUtils.convertToKatakana('漢')) 136 | } 137 | 138 | @Test 139 | fun exampleSentence8() { 140 | KanariaLoader.load() 141 | 142 | var wideResult: WidthUtils.ConvertToWideResult? = null 143 | 144 | wideResult = WidthUtils.convertToWide('ア', 0.toChar()) 145 | Assert.assertEquals('ア', wideResult.result) 146 | Assert.assertFalse(wideResult.isPadding) 147 | 148 | wideResult = WidthUtils.convertToWide('カ', '゙') 149 | Assert.assertEquals('ガ', wideResult.result) 150 | Assert.assertTrue(wideResult.isPadding) 151 | 152 | wideResult = WidthUtils.convertToWide('カ', '゚') 153 | Assert.assertEquals('カ', wideResult.result) 154 | Assert.assertFalse(wideResult.isPadding) 155 | 156 | wideResult = WidthUtils.convertToWide('あ', 0.toChar()) 157 | Assert.assertEquals('あ', wideResult.result) 158 | Assert.assertFalse(wideResult.isPadding) 159 | 160 | var narrowResult: WidthUtils.ConvertToNarrowResult? = null 161 | 162 | narrowResult = WidthUtils.convertToNarrow('ア') 163 | Assert.assertEquals('ア', narrowResult.first) 164 | Assert.assertNull(narrowResult.second) 165 | 166 | narrowResult = WidthUtils.convertToNarrow('ガ') 167 | Assert.assertEquals('カ', narrowResult.first) 168 | Assert.assertEquals('゙', narrowResult.second) 169 | 170 | narrowResult = WidthUtils.convertToNarrow('パ') 171 | Assert.assertEquals('ハ', narrowResult.first) 172 | Assert.assertEquals('゚', narrowResult.second) 173 | 174 | narrowResult = WidthUtils.convertToNarrow('あ') 175 | Assert.assertEquals('あ', narrowResult.first) 176 | Assert.assertNull(narrowResult.second) 177 | 178 | narrowResult = WidthUtils.convertToNarrow('ガ') 179 | Assert.assertEquals('カ', narrowResult.first) 180 | Assert.assertNotEquals(0.toChar(), narrowResult.second) 181 | Assert.assertNotEquals('゚', narrowResult.second) 182 | } 183 | 184 | @Test 185 | fun exampleSentence9() { 186 | val source = "吾輩は😺猫である😺"; 187 | val expect = "吾輩ハ😺猫デアル😺"; 188 | val expect2 = "吾輩ハ😺猫デアル😺"; 189 | 190 | KanariaLoader.load() 191 | Assert.assertEquals(expect, UcsString.from(source).katakana().narrow(UcsString.CONVERT_TARGET_ALL).toString()); 192 | Assert.assertEquals(expect2, UcsString.from(source).katakana().narrow(UcsString.CONVERT_TARGET_NUMBER or UcsString.CONVERT_TARGET_SYMBOL or UcsString.CONVERT_TARGET_ALPHABET).toString()); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /kanaria_jvm/src/test/kotlin/com/kanaria/KanariaLoaderTest.kt: -------------------------------------------------------------------------------- 1 | package com.kanaria 2 | 3 | import org.junit.Test 4 | import kotlin.test.assertEquals 5 | 6 | class KanariaLoaderTest { 7 | @Test 8 | fun loadTest() { 9 | println("name : " + System.getProperty("os.name") + ", arch : " + System.getProperty("os.arch")) 10 | 11 | KanariaLoader.load() 12 | 13 | val actual = UcsString.from("めめめ").katakana().narrow().toString() 14 | println(actual) 15 | assertEquals("メメメ", actual) 16 | } 17 | } -------------------------------------------------------------------------------- /libs/.gitignore: -------------------------------------------------------------------------------- 1 | android-ndk-r20b -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | include("kanaria_core", "kanaria_extern", "kanaria_dotnet", "kanaria_jvm") -------------------------------------------------------------------------------- /setup/install_android_compiler_x86_64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | requireArch="x86_64" 4 | currentArch=$(arch) 5 | 6 | if [ "${currentArch}" != "${requireArch}" ]; then 7 | echo "Not an ${requireArch} architecture." 8 | exit 1 9 | fi 10 | 11 | cd `dirname ${0}` 12 | archiveName=android-ndk-r26d-linux.zip 13 | 14 | wget https://dl.google.com/android/repository/android-ndk-r26d-linux.zip?hl=ja -O $archiveName 15 | unzip $archiveName 16 | rm -f $archiveName 17 | 18 | mv ./android-ndk-r26d ../libs 19 | -------------------------------------------------------------------------------- /setup/install_compiler_x86_64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | requireArch="x86_64" 4 | currentArch=$(arch) 5 | 6 | if [ "${currentArch}" != "${requireArch}" ]; then 7 | echo "Not an ${requireArch} architecture." 8 | exit 1 9 | fi 10 | 11 | apt-get install -y \ 12 | gcc-12 \ 13 | gcc-12-arm-linux-gnueabihf \ 14 | gcc-12-aarch64-linux-gnu \ 15 | gcc-12-i686-linux-gnu \ 16 | mingw-w64 17 | --------------------------------------------------------------------------------