using System; namespace PKHeX.Core; /// /// Logic for converting a between the various generation specific encoding formats. /// public static class StringConverter { /// /// Converts bytes to a string according to the input parameters. /// /// Encoded data /// Generation string format /// Encoding is Japanese /// Encoding is Big Endian /// Decoded string. public static string GetString(ReadOnlySpan data, int generation, bool jp, bool isBigEndian = false) => generation switch { 3 when isBigEndian => StringConverter3GC.GetString(data), 4 when isBigEndian => StringConverter4GC.GetString(data), 1 or 2 => StringConverter12.GetString(data, jp), 3 => StringConverter3.GetString(data, jp), 4 => StringConverter4.GetString(data), 5 => StringConverter5.GetString(data), 6 => StringConverter6.GetString(data), 7 => StringConverter7.GetString(data), 8 => StringConverter8.GetString(data), _ => throw new ArgumentOutOfRangeException(nameof(generation)), }; /// /// Gets the bytes for a Generation specific string according to the input parameters. /// /// Span of bytes to write encoded string data /// Decoded string. /// Maximum length of the input /// Buffer pre-formatting option /// Generation string format /// Encoding is Japanese /// Encoding is Big Endian /// Language specific conversion (Chinese) /// Count of bytes written to the . public static int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option, int generation, bool jp, bool isBigEndian, int language = 0) => generation switch { 3 when isBigEndian => StringConverter3GC.SetString(destBuffer, value, maxLength, option), 4 when isBigEndian => StringConverter4GC.SetString(destBuffer, value, maxLength, option), 1 or 2 => StringConverter12.SetString(destBuffer, value, maxLength, jp, option), 3 => StringConverter3.SetString(destBuffer, value, maxLength, jp, option), 4 => StringConverter4.SetString(destBuffer, value, maxLength, option), 5 => StringConverter5.SetString(destBuffer, value, maxLength, option), 6 => StringConverter6.SetString(destBuffer, value, maxLength, option), 7 => StringConverter7.SetString(destBuffer, value, maxLength, language, option), 8 => StringConverter8.SetString(destBuffer, value, maxLength, option), _ => throw new ArgumentOutOfRangeException(nameof(generation)), }; /// /// Converts full width to single width /// /// Input character to sanitize. internal static char SanitizeChar(char chr) => chr switch { '\uE08F' => '♀', '\uE08E' => '♂', '\u246E' => '♀', '\u246D' => '♂', _ => chr, }; /// /// Converts full width to half width when appropriate /// /// Input character to set back to data /// Checks if the overall string is full-width internal static char UnSanitizeChar(char chr, bool fullWidth = false) { if (fullWidth) // jp/ko/zh strings return chr; // keep as full width return chr switch { '\u2640' => '\uE08F', '\u2642' => '\uE08E', _ => chr, }; } /// /// Converts full width to half width when appropriate, for Gen5 and prior. /// /// Input character to set back to data internal static char UnSanitizeChar5(char chr) => chr switch { '\u2640' => '\u246E', '\u2642' => '\u246D', _ => chr, }; internal static bool GetIsFullWidthString(ReadOnlySpan str) { foreach (var c in str) { if (c >> 12 is (0 or 0xE)) continue; if (c is '\u2640' or '\u2642') // ♀♂ continue; return true; } return false; } public static bool HasEastAsianScriptCharacters(ReadOnlySpan str) { foreach (var c in str) { if (c is >= '\u4E00' and <= '\u9FFF') return true; } return false; } }