Last active
August 15, 2024 00:22
-
-
Save akeit0/b6e52358fa47560a2e032fd3653d8076 to your computer and use it in GitHub Desktop.
RomajiReader Windowsの入力はおそらく全対応
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //These codes are licensed under CC0. | |
| using System; | |
| using System.Collections.Generic; | |
| //using RomajiReader; | |
| // var reader = Reader.Default; | |
| // Console.WriteLine(reader.Convert("shinkyoku"));//しゅんきょく | |
| // Console.WriteLine(reader.Convert("kappa"));//かっぱ | |
| // Console.WriteLine(reader.Convert("cinkya"));//しんきゃ | |
| // Console.WriteLine(reader.Convert("rweqqap"));//rうぇっくぁp | |
| // Console.WriteLine(reader.Convert("RWEQQAP"));//RうぇっくぁP | |
| // Console.WriteLine(reader.Convert("exxnban"));//えっんばn | |
| // Console.WriteLine(reader.Convert("ddhuxkan"));//っでゅヵn | |
| namespace System.Runtime.CompilerServices | |
| { | |
| public class IsExternalInit | |
| { | |
| } | |
| } | |
| namespace RomajiReader | |
| { | |
| public record RomajiElement(string Romaji, string Hiragana, int ConsumeCount) | |
| { | |
| public bool Match(ReadOnlySpan<char> c, out string hiragana, out int consumeCount) | |
| { | |
| hiragana = ""; | |
| consumeCount = 0; | |
| if (c.Length < Romaji.Length) | |
| return false; | |
| var romaji = Romaji.AsSpan(); | |
| for (int i = 0; i < romaji.Length; i++) | |
| if (romaji[i] != c[i]) | |
| return false; | |
| hiragana = Hiragana; | |
| consumeCount = ConsumeCount; | |
| return true; | |
| } | |
| } | |
| public sealed class Reader(IEnumerable<RomajiElement> elements) | |
| { | |
| readonly List<RomajiElement>[] matchMap = ElementsToMap(elements); | |
| static List<RomajiElement>[] ElementsToMap(IEnumerable<RomajiElement> elements) | |
| { | |
| var map = new List<RomajiElement>[27]; | |
| for (int i = 0; i < 27; i++) | |
| { | |
| map[i] = new(); | |
| } | |
| foreach (var element in elements) | |
| { | |
| map[element.Romaji[0] - 'a'].Add(element); | |
| } | |
| return map; | |
| } | |
| static IEnumerable<(string Romaji, string Hiragana)> GetSimpleOnes() | |
| { | |
| return | |
| [ | |
| new("la", "ぁ"), | |
| new("xa", "ぁ"), | |
| new("a", "あ"), | |
| new("li", "ぃ"), | |
| new("lyi", "ぃ"), | |
| new("xi", "ぃ"), | |
| new("xyi", "ぃ"), | |
| new("i", "い"), | |
| new("yi", "い"), | |
| new("ye", "いぇ"), | |
| new("lu", "ぅ"), | |
| new("xu", "ぅ"), | |
| new("u", "う"), | |
| new("whu", "う"), | |
| new("wu", "う"), | |
| new("wha", "うぁ"), | |
| new("wi", "うぃ"), | |
| new("we", "うぇ"), | |
| new("whe", "うぇ"), | |
| new("who", "うぉ"), | |
| new("le", "ぇ"), | |
| new("lye", "ぇ"), | |
| new("xe", "ぇ"), | |
| new("xye", "ぇ"), | |
| new("e", "え"), | |
| new("lo", "ぉ"), | |
| new("xo", "ぉ"), | |
| new("o", "お"), | |
| new("ka", "か"), | |
| new("ga", "が"), | |
| new("ki", "き"), | |
| new("kyi", "きぃ"), | |
| new("kye", "きぇ"), | |
| new("kya", "きゃ"), | |
| new("kyu", "きゅ"), | |
| new("kyo", "きょ"), | |
| new("gi", "ぎ"), | |
| new("gyi", "ぎぃ"), | |
| new("gye", "ぎぇ"), | |
| new("gya", "ぎゃ"), | |
| new("gyu", "ぎゅ"), | |
| new("gyo", "ぎょ"), | |
| new("cu", "く"), | |
| new("ku", "く"), | |
| new("qu", "く"), | |
| new("kwa", "くぁ"), | |
| new("qa", "くぁ"), | |
| new("qwa", "くぁ"), | |
| new("qi", "くぃ"), | |
| new("qwi", "くぃ"), | |
| new("qyi", "くぃ"), | |
| new("qwu", "くぅ"), | |
| new("qe", "くぇ"), | |
| new("qo", "くぉ"), | |
| new("qya", "くゃ"), | |
| new("qyu", "くゅ"), | |
| new("qyo", "くょ"), | |
| new("gu", "ぐ"), | |
| new("gwa", "ぐぁ"), | |
| new("gwi", "ぐぃ"), | |
| new("gwu", "ぐぅ"), | |
| new("gwe", "ぐぇ"), | |
| new("gwo", "ぐぉ"), | |
| new("ke", "け"), | |
| new("ge", "げ"), | |
| new("co", "こ"), | |
| new("ko", "こ"), | |
| new("go", "ご"), | |
| new("sa", "さ"), | |
| new("za", "ざ"), | |
| new("ci", "し"), | |
| new("shi", "し"), | |
| new("si", "し"), | |
| new("syi", "しぃ"), | |
| new("sha", "しゃ"), | |
| new("sya", "しゃ"), | |
| new("shu", "しゅ"), | |
| new("syu", "しゅ"), | |
| new("she", "しぇ"), | |
| new("sye", "しぇ"), | |
| new("syo", "しょ"), | |
| new("sho", "しょ"), | |
| new("ji", "じ"), | |
| new("zi", "じ"), | |
| new("jyi", "じぃ"), | |
| new("zyi", "じぃ"), | |
| new("je", "じぇ"), | |
| new("jye", "じぇ"), | |
| new("zye", "じぇ"), | |
| new("ja", "じゃ"), | |
| new("jya", "じゃ"), | |
| new("zya", "じゃ"), | |
| new("ju", "じゅ"), | |
| new("jyu", "じゅ"), | |
| new("zyu", "じゅ"), | |
| new("jo", "じょ"), | |
| new("jyo", "じょ"), | |
| new("zyo", "じょ"), | |
| new("su", "す"), | |
| new("swa", "すぁ"), | |
| new("swi", "すぃ"), | |
| new("swu", "すぅ"), | |
| new("swe", "すぇ"), | |
| new("swo", "すぉ"), | |
| new("zu", "ず"), | |
| new("ce", "せ"), | |
| new("se", "せ"), | |
| new("ze", "ぜ"), | |
| new("so", "そ"), | |
| new("zo", "ぞ"), | |
| new("ta", "た"), | |
| new("da", "だ"), | |
| new("chi", "ち"), | |
| new("ti", "ち"), | |
| new("cyi", "ちぃ"), | |
| new("tyi", "ちぃ"), | |
| new("che", "ちぇ"), | |
| new("cye", "ちぇ"), | |
| new("tye", "ちぇ"), | |
| new("cha", "ちゃ"), | |
| new("tya", "ちゃ"), | |
| new("chu", "ちゅ"), | |
| new("cyu", "ちゅ"), | |
| new("tyu", "ちゅ"), | |
| new("cho", "ちょ"), | |
| new("cyo", "ちょ"), | |
| new("tyo", "ちょ"), | |
| new("di", "ぢ"), | |
| new("dyi", "ぢぃ"), | |
| new("dye", "ぢぇ"), | |
| new("dya", "ぢゃ"), | |
| new("dyu", "ぢゅ"), | |
| new("dyo", "ぢょ"), | |
| new("ltsu", "っ"), | |
| new("xtu", "っ"), | |
| new("tsu", "つ"), | |
| new("tu", "つ"), | |
| new("tsa", "つぁ"), | |
| new("tsi", "つぃ"), | |
| new("tse", "つぇ"), | |
| new("tso", "つぉ"), | |
| new("du", "づ"), | |
| new("te", "て"), | |
| new("thi", "てぃ"), | |
| new("the", "てぇ"), | |
| new("tha", "てゃ"), | |
| new("thu", "てゅ"), | |
| new("tho", "てょ"), | |
| new("de", "で"), | |
| new("dhi", "でぃ"), | |
| new("dhe", "でぇ"), | |
| new("dha", "でゃ"), | |
| new("dhu", "でゅ"), | |
| new("dho", "でょ"), | |
| new("to", "と"), | |
| new("twa", "とぁ"), | |
| new("twi", "とぃ"), | |
| new("twu", "とぅ"), | |
| new("twe", "とぇ"), | |
| new("two", "とぉ"), | |
| new("do", "ど"), | |
| new("dwa", "どぁ"), | |
| new("dwi", "どぃ"), | |
| new("dwu", "どぅ"), | |
| new("dwe", "どぇ"), | |
| new("dwo", "どぉ"), | |
| new("na", "な"), | |
| new("ni", "に"), | |
| new("nyi", "にぃ"), | |
| new("nye", "にぇ"), | |
| new("nya", "にゃ"), | |
| new("nyu", "にゅ"), | |
| new("nyo", "にょ"), | |
| new("nu", "ぬ"), | |
| new("ne", "ね"), | |
| new("no", "の"), | |
| new("ha", "は"), | |
| new("ba", "ば"), | |
| new("pa", "ぱ"), | |
| new("hi", "ひ"), | |
| new("hyi", "ひぃ"), | |
| new("hye", "ひぇ"), | |
| new("hya", "ひゃ"), | |
| new("hyu", "ひゅ"), | |
| new("hyo", "ひょ"), | |
| new("bi", "び"), | |
| new("byi", "びぃ"), | |
| new("bye", "びぇ"), | |
| new("bya", "びゃ"), | |
| new("byu", "びゅ"), | |
| new("byo", "びょ"), | |
| new("pi", "ぴ"), | |
| new("pyi", "ぴぃ"), | |
| new("pye", "ぴぇ"), | |
| new("pya", "ぴゃ"), | |
| new("pyu", "ぴゅ"), | |
| new("pyo", "ぴょ"), | |
| new("fu", "ふ"), | |
| new("hu", "ふ"), | |
| new("fa", "ふぁ"), | |
| new("fwa", "ふぁ"), | |
| new("fi", "ふぃ"), | |
| new("fwi", "ふぃ"), | |
| new("fyi", "ふぃ"), | |
| new("fwu", "ふぅ"), | |
| new("fe", "ふぇ"), | |
| new("fo", "ふぉ"), | |
| new("fwo", "ふぉ"), | |
| new("fya", "ふゃ"), | |
| new("fyu", "ふゅ"), | |
| new("fyo", "ふょ"), | |
| new("bu", "ぶ"), | |
| new("pu", "ぷ"), | |
| new("he", "へ"), | |
| new("be", "べ"), | |
| new("pe", "ぺ"), | |
| new("ho", "ほ"), | |
| new("bo", "ぼ"), | |
| new("po", "ぽ"), | |
| new("ma", "ま"), | |
| new("mi", "み"), | |
| new("myi", "みぃ"), | |
| new("mye", "みぇ"), | |
| new("mya", "みゃ"), | |
| new("myu", "みゅ"), | |
| new("myo", "みょ"), | |
| new("mu", "む"), | |
| new("me", "め"), | |
| new("mo", "も"), | |
| new("lya", "ゃ"), | |
| new("xya", "ゃ"), | |
| new("ya", "や"), | |
| new("lyu", "ゅ"), | |
| new("xyu", "ゅ"), | |
| new("yu", "ゆ"), | |
| new("lyo", "ょ"), | |
| new("xyo", "ょ"), | |
| new("yo", "よ"), | |
| new("ra", "ら"), | |
| new("ri", "り"), | |
| new("ryi", "りぃ"), | |
| new("rye", "りぇ"), | |
| new("rya", "りゃ"), | |
| new("ryu", "りゅ"), | |
| new("ryo", "りょ"), | |
| new("ru", "る"), | |
| new("re", "れ"), | |
| new("ro", "ろ"), | |
| new("lwa", "ゎ"), | |
| new("xwa", "ゎ"), | |
| new("wa", "わ"), | |
| new("wyi", "ゐ"), | |
| new("wye", "ゑ"), | |
| new("wo", "を"), | |
| new("nn", "ん"), | |
| new("xn", "ん"), | |
| new("vu", "ヴ"), | |
| new("va", "ヴぁ"), | |
| new("vi", "ヴぃ"), | |
| new("vyi", "ヴぃ"), | |
| new("ve", "ヴぇ"), | |
| new("vye", "ヴぇ"), | |
| new("vo", "ヴぉ"), | |
| new("vya", "ヴゃ"), | |
| new("vyu", "ヴゅ"), | |
| new("vyo", "ヴょ"), | |
| new("lka", "ヵ"), | |
| new("xka", "ヵ"), | |
| new("lke", "ヶ"), | |
| new("xke", "ヶ"), | |
| ]; | |
| } | |
| static IEnumerable<RomajiElement> DefaultAll() | |
| { | |
| foreach (var (romaji, hiragana) in GetSimpleOnes()) | |
| { | |
| yield return new(romaji, hiragana, romaji.Length); | |
| if (romaji[0] is not ('a' or 'i' or 'u' or 'e' or 'o')) | |
| { | |
| if (romaji[0] != 'n' && romaji[0] != 'y') | |
| { | |
| yield return new("n" + romaji, "ん", 1); | |
| } | |
| yield return new(romaji[0] + romaji, "っ" + hiragana, romaji.Length + 1); | |
| } | |
| } | |
| } | |
| public static Reader Default { get; } = new(DefaultAll()); | |
| char[] loweredBuffer = new char[128]; | |
| char[] rawBuffer = new char[128]; | |
| public void Convert(ReadOnlySpan<char> text, List<char> result) | |
| { | |
| var count = 0; | |
| result.Clear(); | |
| foreach (var c in text) | |
| { | |
| if (count >= loweredBuffer.Length) | |
| { | |
| Array.Resize(ref loweredBuffer, loweredBuffer.Length * 2); | |
| Array.Resize(ref rawBuffer, rawBuffer.Length * 2); | |
| } | |
| //大文字と小文字はunicodeで差が32 | |
| loweredBuffer[count] = (c is >= 'A' and <= 'Z')? (char)(c + 32) : c; | |
| rawBuffer[count] = c; | |
| count++; | |
| } | |
| var remainCount = count; | |
| while (0 < remainCount) | |
| { | |
| var start = count - remainCount; | |
| var firstChar = loweredBuffer[start]; | |
| if (firstChar is >= 'a' and <= 'z') | |
| { | |
| foreach (var element in matchMap[firstChar - 'a']) | |
| { | |
| if (element.Match(loweredBuffer.AsSpan(start, remainCount), out var hiragana, out var consumeCount)) | |
| { | |
| foreach (var c in hiragana) | |
| { | |
| result.Add(c); | |
| } | |
| remainCount -= consumeCount; | |
| break; | |
| } | |
| } | |
| } | |
| if (remainCount == 0) return; | |
| if ((start + remainCount) != count) continue; | |
| result.Add(rawBuffer[start]); | |
| remainCount--; | |
| } | |
| } | |
| readonly List<char> resultCache = new(); | |
| public string Convert(ReadOnlySpan<char> text) | |
| { | |
| var result = resultCache; | |
| result.Clear(); | |
| Convert(text, result); | |
| return string.Create(result.Count, result, (span, list) => | |
| { | |
| for (int i = 0; i < span.Length; i++) | |
| { | |
| span[i] = list[i]; | |
| } | |
| list.Clear(); | |
| }); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment