Top / .NET備忘録 / 11.文字列の扱い / 05.StrConvEx(改良版)

LCMapStringW での実装は、思ったより簡単でした。
というか、ほぼ何も考えなくて良いので、こっちのほうがだいぶ楽でしたね。orz

 [Flags]
 public enum VbStrConvEx
 {
     UpperCase = 0x01,
     LowerCase = 0x02,
     ProperCase = 0x03,
     Wide = 0x04,
     Narrow = 0x08,
     Katakana = 0x10,
     Hiragana = 0x20,
     Unicode = 0x40,
     FromUnicode = 0x80,
     SimplifiedChinese = 0x100,
     TraditionalChinese = 0x200,
     LinguisticCasing = 0x400,
 }
 
 private static Encoding encShiftJis = Encoding.GetEncoding("Shift_JIS");
 
 public static VBString StrConvEx(VBString value, VbStrConvEx Conversion)
 {
     if ((object)value == null) return string.Empty;
     if (value.LengthB == 0) return string.Empty;
 
     // vbUnicode は先に変換する
 
     if ((Conversion & VbStrConvEx.Unicode) == VbStrConvEx.Unicode)
     {
         value = encShiftJis.GetString(value.ToByteArray());
         Conversion = Conversion & ~VbStrConvEx.Unicode;
     }
 
     // vbFromUnicode は後で変換するので、フラグとして保存する
     bool fromUnicode = (Conversion & VbStrConvEx.FromUnicode) == VbStrConvEx.FromUnicode;
     Conversion = Conversion & ~VbStrConvEx.FromUnicode;
 
     // LCMapString の呼び出し
     if (Conversion != 0)
         value = LCMapStringCaller(value, (VbStrConv)Conversion, 0);
 
     // シフト JIS に変換
     if (fromUnicode)
         return encShiftJis.GetBytes(value);
     else
         return value;
 }
 
 private const int
     LCMAP_LOWERCASE = 0x00000100,                   // lower case letters
     LCMAP_UPPERCASE = 0x00000200,                   // upper case letters
     LCMAP_SORTKEY = 0x00000400,                     // WC sort key (normalize)
     LCMAP_BYTEREV = 0x00000800,                     // byte reversal
     LCMAP_HIRAGANA = 0x00100000,                    // map katakana to hiragana
     LCMAP_KATAKANA = 0x00200000,                    // map hiragana to katakana
     LCMAP_HALFWIDTH = 0x00400000,                   // map double byte to single byte
     LCMAP_FULLWIDTH = 0x00800000,                   // map single byte to double byte
     LCMAP_LINGUISTIC_CASING = 0x01000000,           // use linguistic rules for casing
     LCMAP_SIMPLIFIED_CHINESE = 0x02000000,          // map traditional chinese to simplified chinese
     LCMAP_TRADITIONAL_CHINESE = 0x04000000;         // map simplified chinese to traditional chinese
 
 [DllImport("kernel32", CharSet = CharSet.Auto, ExactSpelling = false, SetLastError = true)]
 private static extern int LCMapString(
                         int Locale,
                         int dwMapFlags,
                         [MarshalAs(UnmanagedType.LPTStr)] string lpSrcStr,
                         int cchSrc,
                         IntPtr lpDestStr,
                         int cchDest);
 
 // LCMapString の呼び出し
 private static string LCMapStringCaller(string str, VbStrConv Conversion, int LocaleID = 0)
 {
     // LocaleID から cultureInfo を取得
 
     CultureInfo cultureInfo;
     if (LocaleID == 0 || LocaleID == 1)
     {
         cultureInfo = Thread.CurrentThread.CurrentCulture;
         LocaleID = cultureInfo.LCID;
     }
     else
     {
         cultureInfo = new CultureInfo(LocaleID & 65535);
     }
 
     int dwMapFlags = 0;
     bool properCase = (Conversion & VbStrConv.ProperCase) == VbStrConv.ProperCase;
 
     // ProperCase(3) が指定されていなければ、Uppercase(1) と Lowercase(2) が有効
 
     if (!properCase)
     {
         if ((Conversion & VbStrConv.Uppercase) == VbStrConv.Uppercase) dwMapFlags |= LCMAP_UPPERCASE;
         if ((Conversion & VbStrConv.Lowercase) == VbStrConv.Lowercase) dwMapFlags |= LCMAP_LOWERCASE;
     }
 
     // その他のフラグを設定
 
     if ((Conversion & VbStrConv.Wide) == VbStrConv.Wide) dwMapFlags |= LCMAP_FULLWIDTH;
     if ((Conversion & VbStrConv.Narrow) == VbStrConv.Narrow) dwMapFlags |= LCMAP_HALFWIDTH;
 
     if ((Conversion & VbStrConv.Hiragana) == VbStrConv.Hiragana) dwMapFlags |= LCMAP_HIRAGANA;
     if ((Conversion & VbStrConv.Katakana) == VbStrConv.Katakana) dwMapFlags |= LCMAP_KATAKANA;
 
     if ((Conversion & VbStrConv.SimplifiedChinese) == VbStrConv.SimplifiedChinese) dwMapFlags |= LCMAP_SIMPLIFIED_CHINESE;
     if ((Conversion & VbStrConv.TraditionalChinese) == VbStrConv.TraditionalChinese) dwMapFlags |= LCMAP_TRADITIONAL_CHINESE;
     if ((Conversion & VbStrConv.LinguisticCasing) == VbStrConv.LinguisticCasing) dwMapFlags |= LCMAP_LINGUISTIC_CASING;
 
     // 必要なバッファ長を調べ、アンマネージメモリを確保する
 
     int stringLength = LCMapString(cultureInfo.LCID, dwMapFlags, str, str.Length, IntPtr.Zero, 0);
     if (stringLength == 0)
     {
         throw new Win32Exception();
     }
 
     // 文字数が返るので2倍のバイト数が必要
 
     int byteLength = stringLength * 2;
     IntPtr buffer = Marshal.AllocHGlobal(byteLength);
 
     try
     {
         // 変換
         stringLength = LCMapString(cultureInfo.LCID, dwMapFlags, str, str.Length, buffer, byteLength);
         if (stringLength == 0)
         {
             throw new Win32Exception();
         }
 
         string returnString = Marshal.PtrToStringAuto(buffer, stringLength);
 
         // ProperCase が指定されていれば変換(全角アルファベットもOK)
         if (properCase)
             return cultureInfo.TextInfo.ToTitleCase(returnString);
 
         return returnString;
     }
     finally
     {
         // アンマネージメモリを解放
         Marshal.FreeHGlobal(buffer);
     }
 }



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-09-13 (金) 00:45:34 (1555d)