Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Last active December 11, 2015 00:39
Show Gist options
  • Save azyobuzin/4518124 to your computer and use it in GitHub Desktop.
Save azyobuzin/4518124 to your computer and use it in GitHub Desktop.
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace StrConvInCSharp
{
public static class MapStringExWrapper
{
[DllImport("Kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int LCMapStringEx(string lpLocaleName, uint dwMapFlags, string lpSrcStr, int cchSrc, [MarshalAs(UnmanagedType.LPArray)] char[] lpDestStr, int cchDest, ref NLSVERSIONINFO lpVersionInformation, IntPtr lpReserved, IntPtr sortHandle);
private const string LOCALE_NAME_INVARIANT = "";
private const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale";
private const string LOCALE_NAME_USER_DEFAULT = null;
private const uint LCMAP_BYTEREV = 0x00000800;
private const uint LCMAP_FULLWIDTH = 0x00800000;
private const uint LCMAP_HALFWIDTH = 0x00400000;
private const uint LCMAP_HIRAGANA = 0x00100000;
private const uint LCMAP_KATAKANA = 0x00200000;
private const uint LCMAP_LINGUISTIC_CASING = 0x01000000;
private const uint LCMAP_LOWERCASE = 0x00000100;
private const uint LCMAP_SIMPLIFIED_CHINESE = 0x02000000;
private const uint LCMAP_SORTKEY = 0x00000400;
private const uint LCMAP_TITLECASE = 0x00000300;
private const uint LCMAP_TRADITIONAL_CHINESE = 0x04000000;
private const uint LCMAP_UPPERCASE = 0x00000200;
private const uint NORM_IGNORENONSPACE = 0x00000002;
private const uint NORM_IGNORESYMBOLS = 0x00000004;
private const uint LINGUISTIC_IGNORECASE = 0x00000010;
private const uint LINGUISTIC_IGNOREDIACRITIC = 0x00000020;
private const uint NORM_IGNORECASE = 0x00000001;
private const uint NORM_IGNOREKANATYPE = 0x00010000;
private const uint NORM_IGNOREWIDTH = 0x00020000;
private const uint NORM_LINGUISTIC_CASING = 0x08000000;
private const uint SORT_DIGITSASNUMBERS = 0x00000008;
private const uint SORT_STRINGSORT = 0x00001000;
[StructLayout(LayoutKind.Sequential)]
private struct NLSVERSIONINFO
{
public uint dwNLSVersionInfoSize;
public uint dwNLSVersion;
public uint dwDefinedVersion;
}
/// <summary>
/// http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd318702.aspx
/// http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd318144.aspx
/// </summary>
public enum MapFlag : uint
{
/// <summary>
/// バイトを反転させます。
/// </summary>
ByteReverse = LCMAP_BYTEREV,
/// <summary>
/// 全角に変換します。
/// </summary>
FullWidth = LCMAP_FULLWIDTH,
/// <summary>
/// 半角に変換します。
/// </summary>
HalfWidth = LCMAP_HALFWIDTH,
/// <summary>
/// ひらがなに変換します。
/// </summary>
Hiragana = LCMAP_HIRAGANA,
/// <summary>
/// カタカナに変換します。
/// </summary>
Katakana = LCMAP_KATAKANA,
/// <summary>
/// ケースに言語学上のルールを適用します。(翻訳失敗)
/// </summary>
LinguisticCasing = LCMAP_LINGUISTIC_CASING,
/// <summary>
/// 小文字に変換します。
/// </summary>
LowerCase = LCMAP_LOWERCASE,
/// <summary>
/// 簡体字に変換します。
/// </summary>
SimplifiedChinese = LCMAP_SIMPLIFIED_CHINESE,
/// <summary>
/// ソートキーを生成します。(要調査)
/// </summary>
SortKey = LCMAP_SORTKEY,
/// <summary>
/// タイトルケースに変換します。
/// </summary>
TitleCase = LCMAP_TITLECASE,
/// <summary>
/// 繁体字に変換します。
/// </summary>
TraditionalChinese = LCMAP_TRADITIONAL_CHINESE,
/// <summary>
/// 大文字に変換します。
/// </summary>
UpperCase = LCMAP_UPPERCASE,
/// <summary>
/// (要調査) ByteReverse または SortKey のみが指定されている場合に指定できます。
/// </summary>
NormIgnoreNonspace = NORM_IGNORENONSPACE,
/// <summary>
/// (要調査) ByteReverse または SortKey のみが指定されている場合に指定できます。
/// </summary>
NormIgnoreSymbols = NORM_IGNORESYMBOLS,
/// <summary>
/// 言語的に適切なものとして大文字小文字を無視します。 SortKey のみが指定されている場合に指定できます。(翻訳失敗)
/// </summary>
LinguisticIgnoreCase = LINGUISTIC_IGNORECASE,
/// <summary>
/// 言語的に適切なものとして非スペーシングを無視します。 SortKey のみが指定されている場合に指定できます。(翻訳失敗)
/// </summary>
LinguisticIgnoreDiacritic = LINGUISTIC_IGNOREDIACRITIC,
/// <summary>
/// (要調査) SortKey のみが指定されている場合に指定できます。
/// </summary>
NormIgnoreCase = NORM_IGNORECASE,
/// <summary>
/// ひらがなとカタカナが等しいものとして扱います。 SortKey のみが指定されている場合に指定できます。
/// </summary>
NormIgnoreKanaType = NORM_IGNOREKANATYPE,
/// <summary>
/// 全角文字と半角文字が等しいものとして扱います。 SortKey のみが指定されている場合に指定できます。
/// </summary>
NormIgnoreWidth = NORM_IGNOREWIDTH,
/// <summary>
/// ケースに言語学上のルールを適用します。 SortKey のみが指定されている場合に指定できます。(翻訳失敗)
/// </summary>
NormLinguisticCasing = NORM_LINGUISTIC_CASING,
/// <summary>
/// (要調査) SortKey のみが指定されている場合に指定できます。
/// </summary>
SortDigitsAsNumbers = SORT_DIGITSASNUMBERS,
/// <summary>
/// ストリングソートを行います。 SortKey のみが指定されている場合に指定できます。
/// </summary>
StringSort = SORT_STRINGSORT
}
public static string MapString(string source, MapFlag flags, string locale = LOCALE_NAME_USER_DEFAULT)
{
if (source == null)
throw new ArgumentNullException("source");
if (source.Length == 0)
throw new ArgumentException("source が空です。", "source");
var result = new char[Math.Min(source.Length * 10L, int.MaxValue)]; //余裕を持って
var verinfo = new NLSVERSIONINFO();
//object reserved = null;
var count = LCMapStringEx(locale, (uint)flags, source, source.Length, result, result.Length, ref verinfo, IntPtr.Zero, IntPtr.Zero);
if (count == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
return string.Join("", result.Take(count));
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace StrConvInCSharp
{
class Program
{
static void Main(string[] args)
{
try
{
var result = MapStringExWrapper.MapString(
"test",
MapStringExWrapper.MapFlag.UpperCase
);
Console.WriteLine(result);
//Encoding.Unicode.GetBytes(result).ForEach(b => Console.WriteLine(Convert.ToString(b, 16).ToUpper()));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment