OSDN Git Service

.NET FW が対応していない文字コード名に対応
authorkomutan <t_komuta@nifty.com>
Mon, 23 Mar 2015 09:45:31 +0000 (18:45 +0900)
committerkomutan <t_komuta@nifty.com>
Mon, 23 Mar 2015 09:45:31 +0000 (18:45 +0900)
src/LibNMeCab/Core/MeCabDictionary.cs
src/LibNMeCab/Core/StrUtils.cs

index 79a1fee..77158c2 100644 (file)
-//  MeCab -- Yet Another Part-of-Speech and Morphological Analyzer\r
-//\r
-//  Copyright(C) 2001-2006 Taku Kudo <taku@chasen.org>\r
-//  Copyright(C) 2004-2006 Nippon Telegraph and Telephone Corporation\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.IO;\r
-#if MMF_DIC\r
-using System.IO.MemoryMappedFiles;\r
-#endif\r
-\r
-namespace NMeCab.Core\r
-{\r
-    public class MeCabDictionary : IDisposable\r
-    {\r
-        #region  Const/Field/Property\r
-\r
-        private const uint DictionaryMagicID = 0xEF718F77u;\r
-        private const uint DicVersion = 102u;\r
-\r
-#if MMF_DIC\r
-        private MemoryMappedFile mmf;\r
-        private MemoryMappedViewAccessor tokens;\r
-        private MemoryMappedViewAccessor features;\r
-#else\r
-        private Token[] tokens;\r
-        private byte[] features;\r
-#endif\r
-\r
-        private DoubleArray da = new DoubleArray();\r
-\r
-        private Encoding encoding;\r
-\r
-        /// <summary>\r
-        /// 辞書の文字コード\r
-        /// </summary>\r
-        public string CharSet\r
-        {\r
-            get { return this.encoding.WebName; }\r
-        }\r
-\r
-        /// <summary>\r
-        /// バージョン\r
-        /// </summary>\r
-        public uint Version { get; private set; }\r
-\r
-        /// <summary>\r
-        /// 辞書のタイプ\r
-        /// </summary>\r
-        public DictionaryType Type { get; private set; }\r
-\r
-        public uint LexSize { get; private set; }\r
-\r
-        /// <summary>\r
-        /// 左文脈 ID のサイズ\r
-        /// </summary>\r
-        public uint LSize { get; private set; }\r
-\r
-        /// <summary>\r
-        /// 右文脈 ID のサイズ\r
-        /// </summary>\r
-        public uint RSize { get; private set; }\r
-\r
-        /// <summary>\r
-        /// 辞書のファイル名\r
-        /// </summary>\r
-        public string FileName { get; private set; }\r
-\r
-        #endregion\r
-\r
-        #region Open\r
-\r
-#if MMF_DIC\r
-\r
-        public void Open(string filePath)\r
-        {\r
-            this.mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open,\r
-                                                       null, 0L, MemoryMappedFileAccess.Read);\r
-            this.Open(this.mmf, filePath);\r
-        }\r
-\r
-        public void Open(MemoryMappedFile mmf, string filePath = null)\r
-        {\r
-            this.FileName = filePath;\r
-\r
-            using (MemoryMappedViewStream stream = mmf.CreateViewStream(\r
-                                                        0L, 0L, MemoryMappedFileAccess.Read))\r
-            using (BinaryReader reader = new BinaryReader(stream))\r
-            {\r
-                uint magic = reader.ReadUInt32();\r
-                if (stream.CanSeek && stream.Length < (magic ^ DictionaryMagicID)) //正確なサイズ取得ができないので不等号で代用\r
-                    throw new MeCabInvalidFileException("dictionary file is broken", filePath);\r
-\r
-                this.Version = reader.ReadUInt32();\r
-                if (this.Version != DicVersion)\r
-                    throw new MeCabInvalidFileException("incompatible version", filePath);\r
-\r
-                this.Type = (DictionaryType)reader.ReadUInt32();\r
-                this.LexSize = reader.ReadUInt32();\r
-                this.LSize = reader.ReadUInt32();\r
-                this.RSize = reader.ReadUInt32();\r
-                uint dSize = reader.ReadUInt32();\r
-                uint tSize = reader.ReadUInt32();\r
-                uint fSize = reader.ReadUInt32();\r
-                reader.ReadUInt32(); //dummy\r
-\r
-                string charSet = StrUtils.GetString(reader.ReadBytes(32), Encoding.ASCII);\r
-                this.encoding = Encoding.GetEncoding(charSet);\r
-\r
-                long offset = stream.Position;\r
-                this.da.Open(mmf, offset, dSize);\r
-                offset += dSize;\r
-                this.tokens = mmf.CreateViewAccessor(offset, tSize, MemoryMappedFileAccess.Read);\r
-                offset += tSize;\r
-                this.features = mmf.CreateViewAccessor(offset, fSize, MemoryMappedFileAccess.Read);\r
-            }\r
-        }\r
-\r
-#else\r
-\r
-        public void Open(string filePath)\r
-        {\r
-            this.FileName = filePath;\r
-            \r
-            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))\r
-            using (BinaryReader reader = new BinaryReader(fileStream))\r
-            {\r
-                this.Open(reader);\r
-            }\r
-        }\r
-\r
-        public unsafe void Open(BinaryReader reader)\r
-        {\r
-            uint magic = reader.ReadUInt32();\r
-            //CanSeekの時のみストリーム長のチェック\r
-            if (reader.BaseStream.CanSeek && reader.BaseStream.Length != (magic ^ DictionaryMagicID))\r
-                throw new MeCabInvalidFileException("dictionary file is broken", this.FileName);\r
-\r
-            this.Version = reader.ReadUInt32();\r
-            if (this.Version != DicVersion)\r
-                throw new MeCabInvalidFileException("incompatible version", this.FileName);\r
-\r
-            this.Type = (DictionaryType)reader.ReadUInt32();\r
-            this.LexSize = reader.ReadUInt32();\r
-            this.LSize = reader.ReadUInt32();\r
-            this.RSize = reader.ReadUInt32();\r
-            uint dSize = reader.ReadUInt32();\r
-            uint tSize = reader.ReadUInt32();\r
-            uint fSize = reader.ReadUInt32();\r
-            reader.ReadUInt32(); //dummy\r
-\r
-            string charSet = StrUtils.GetString(reader.ReadBytes(32), Encoding.ASCII);\r
-            this.encoding = Encoding.GetEncoding(charSet);\r
-\r
-            this.da.Open(reader, dSize);\r
-\r
-            this.tokens = new Token[tSize / sizeof(Token)];\r
-            for (int i = 0; i < this.tokens.Length; i++)\r
-                this.tokens[i] = Token.Create(reader);\r
-\r
-            this.features = reader.ReadBytes((int)fSize);\r
-\r
-            if (reader.BaseStream.ReadByte() != -1)\r
-                throw new MeCabInvalidFileException("dictionary file is broken", this.FileName);\r
-        }\r
-\r
-#endif\r
-\r
-        #endregion\r
-\r
-        #region Search\r
-\r
-        public unsafe DoubleArray.ResultPair ExactMatchSearch(string key)\r
-        {\r
-            fixed (char* pKey = key)\r
-                return this.ExactMatchSearch(pKey, key.Length, 0);\r
-        }\r
-\r
-        public unsafe DoubleArray.ResultPair ExactMatchSearch(char* key, int len, int nodePos = 0)\r
-        {\r
-            //if (this.encoding == Encoding.Unicode)\r
-            //    return this.da.ExactMatchSearch((byte*)key, len, nodePos);\r
-\r
-            //エンコード\r
-            int maxByteCount = this.encoding.GetMaxByteCount(len);\r
-            byte* bytes = stackalloc byte[maxByteCount];\r
-            int bytesLen = this.encoding.GetBytes(key, len, bytes, maxByteCount);\r
-\r
-            DoubleArray.ResultPair result = this.da.ExactMatchSearch(bytes, bytesLen, nodePos);\r
-\r
-            //文字数をデコードしたものに変換\r
-            result.Length = this.encoding.GetCharCount(bytes, result.Length);\r
-\r
-            return result;\r
-        }\r
-\r
-        public unsafe int CommonPrefixSearch(char* key, int len, DoubleArray.ResultPair* result, int rLen)\r
-        {\r
-            //if (this.encoding == Encoding.Unicode)\r
-            //    return this.da.CommonPrefixSearch((byte*)key, result, rLen, len);\r
-\r
-            //エンコード\r
-            int maxByteLen = this.encoding.GetMaxByteCount(len);\r
-            byte* bytes = stackalloc byte[maxByteLen];\r
-            int bytesLen = this.encoding.GetBytes(key, len, bytes, maxByteLen);\r
-\r
-            int n = this.da.CommonPrefixSearch(bytes, result, rLen, bytesLen);\r
-\r
-            //文字数をデコードしたものに変換\r
-            for (int i = 0; i < n; i++)\r
-                result[i].Length = this.encoding.GetCharCount(bytes, result[i].Length);\r
-\r
-            return n;\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region Get Infomation\r
-\r
-        public unsafe Token[] GetToken(DoubleArray.ResultPair n)\r
-        {\r
-            Token[] dist = new Token[0xFF & n.Value];\r
-            int tokenPos = n.Value >> 8;\r
-#if MMF_DIC\r
-            this.tokens.ReadArray<Token>(tokenPos * sizeof(Token), dist, 0, dist.Length);\r
-#else\r
-            Array.Copy(this.tokens, tokenPos, dist, 0, dist.Length);\r
-#endif\r
-            return dist;\r
-        }\r
-\r
-        public string GetFeature(uint featurePos)\r
-        {\r
-            return StrUtils.GetString(this.features, (long)featurePos, this.encoding);\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region etc.\r
-\r
-        public bool IsCompatible(MeCabDictionary d)\r
-        {\r
-            return (this.Version == d.Version &&\r
-                    this.LSize == d.LSize &&\r
-                    this.RSize == d.RSize &&\r
-                    this.CharSet == d.CharSet);\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region Dispose\r
-\r
-        private bool disposed;\r
-\r
-        /// <summary>\r
-        /// 使用されているリソースを開放する\r
-        /// </summary>\r
-        public void Dispose()\r
-        {\r
-            this.Dispose(true);\r
-            GC.SuppressFinalize(this);\r
-        }\r
-\r
-        protected virtual void Dispose(bool disposing)\r
-        {\r
-            if (disposed) return;\r
-\r
-            if (disposing)\r
-            {\r
-                if (this.da != null) this.da.Dispose();\r
-#if MMF_DIC\r
-                if (this.mmf != null) this.mmf.Dispose();\r
-                if (this.tokens != null) this.tokens.Dispose();\r
-                if (this.features != null) this.features.Dispose();\r
-#endif\r
-            }\r
-\r
-            this.disposed = true;\r
-        }\r
-\r
-        ~MeCabDictionary()\r
-        {\r
-            this.Dispose(false);\r
-        }\r
-\r
-        #endregion\r
-    }\r
-}\r
+//  MeCab -- Yet Another Part-of-Speech and Morphological Analyzer
+//
+//  Copyright(C) 2001-2006 Taku Kudo <taku@chasen.org>
+//  Copyright(C) 2004-2006 Nippon Telegraph and Telephone Corporation
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+#if MMF_DIC
+using System.IO.MemoryMappedFiles;
+#endif
+
+namespace NMeCab.Core
+{
+    public class MeCabDictionary : IDisposable
+    {
+        #region  Const/Field/Property
+
+        private const uint DictionaryMagicID = 0xEF718F77u;
+        private const uint DicVersion = 102u;
+
+#if MMF_DIC
+        private MemoryMappedFile mmf;
+        private MemoryMappedViewAccessor tokens;
+        private MemoryMappedViewAccessor features;
+#else
+        private Token[] tokens;
+        private byte[] features;
+#endif
+
+        private DoubleArray da = new DoubleArray();
+
+        private Encoding encoding;
+
+        /// <summary>
+        /// 辞書の文字コード
+        /// </summary>
+        public string CharSet
+        {
+            get { return this.encoding.WebName; }
+        }
+
+        /// <summary>
+        /// バージョン
+        /// </summary>
+        public uint Version { get; private set; }
+
+        /// <summary>
+        /// 辞書のタイプ
+        /// </summary>
+        public DictionaryType Type { get; private set; }
+
+        public uint LexSize { get; private set; }
+
+        /// <summary>
+        /// 左文脈 ID のサイズ
+        /// </summary>
+        public uint LSize { get; private set; }
+
+        /// <summary>
+        /// 右文脈 ID のサイズ
+        /// </summary>
+        public uint RSize { get; private set; }
+
+        /// <summary>
+        /// 辞書のファイル名
+        /// </summary>
+        public string FileName { get; private set; }
+
+        #endregion
+
+        #region Open
+
+#if MMF_DIC
+
+        public void Open(string filePath)
+        {
+            this.mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open,
+                                                       null, 0L, MemoryMappedFileAccess.Read);
+            this.Open(this.mmf, filePath);
+        }
+
+        public void Open(MemoryMappedFile mmf, string filePath = null)
+        {
+            this.FileName = filePath;
+
+            using (MemoryMappedViewStream stream = mmf.CreateViewStream(
+                                                        0L, 0L, MemoryMappedFileAccess.Read))
+            using (BinaryReader reader = new BinaryReader(stream))
+            {
+                uint magic = reader.ReadUInt32();
+                if (stream.CanSeek && stream.Length < (magic ^ DictionaryMagicID)) //正確なサイズ取得ができないので不等号で代用
+                    throw new MeCabInvalidFileException("dictionary file is broken", filePath);
+
+                this.Version = reader.ReadUInt32();
+                if (this.Version != DicVersion)
+                    throw new MeCabInvalidFileException("incompatible version", filePath);
+
+                this.Type = (DictionaryType)reader.ReadUInt32();
+                this.LexSize = reader.ReadUInt32();
+                this.LSize = reader.ReadUInt32();
+                this.RSize = reader.ReadUInt32();
+                uint dSize = reader.ReadUInt32();
+                uint tSize = reader.ReadUInt32();
+                uint fSize = reader.ReadUInt32();
+                reader.ReadUInt32(); //dummy
+
+                string charSet = StrUtils.GetString(reader.ReadBytes(32), Encoding.ASCII);
+                this.encoding = StrUtils.GetEncoding(charSet);
+
+                long offset = stream.Position;
+                this.da.Open(mmf, offset, dSize);
+                offset += dSize;
+                this.tokens = mmf.CreateViewAccessor(offset, tSize, MemoryMappedFileAccess.Read);
+                offset += tSize;
+                this.features = mmf.CreateViewAccessor(offset, fSize, MemoryMappedFileAccess.Read);
+            }
+        }
+
+#else
+
+        public void Open(string filePath)
+        {
+            this.FileName = filePath;
+            
+            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+            using (BinaryReader reader = new BinaryReader(fileStream))
+            {
+                this.Open(reader);
+            }
+        }
+
+        public unsafe void Open(BinaryReader reader)
+        {
+            uint magic = reader.ReadUInt32();
+            //CanSeekの時のみストリーム長のチェック
+            if (reader.BaseStream.CanSeek && reader.BaseStream.Length != (magic ^ DictionaryMagicID))
+                throw new MeCabInvalidFileException("dictionary file is broken", this.FileName);
+
+            this.Version = reader.ReadUInt32();
+            if (this.Version != DicVersion)
+                throw new MeCabInvalidFileException("incompatible version", this.FileName);
+
+            this.Type = (DictionaryType)reader.ReadUInt32();
+            this.LexSize = reader.ReadUInt32();
+            this.LSize = reader.ReadUInt32();
+            this.RSize = reader.ReadUInt32();
+            uint dSize = reader.ReadUInt32();
+            uint tSize = reader.ReadUInt32();
+            uint fSize = reader.ReadUInt32();
+            reader.ReadUInt32(); //dummy
+
+            string charSet = StrUtils.GetString(reader.ReadBytes(32), Encoding.ASCII);
+            this.encoding = StrUtils.GetEncoding(charSet);
+
+            this.da.Open(reader, dSize);
+
+            this.tokens = new Token[tSize / sizeof(Token)];
+            for (int i = 0; i < this.tokens.Length; i++)
+                this.tokens[i] = Token.Create(reader);
+
+            this.features = reader.ReadBytes((int)fSize);
+
+            if (reader.BaseStream.ReadByte() != -1)
+                throw new MeCabInvalidFileException("dictionary file is broken", this.FileName);
+        }
+
+#endif
+
+        #endregion
+
+        #region Search
+
+        public unsafe DoubleArray.ResultPair ExactMatchSearch(string key)
+        {
+            fixed (char* pKey = key)
+                return this.ExactMatchSearch(pKey, key.Length, 0);
+        }
+
+        public unsafe DoubleArray.ResultPair ExactMatchSearch(char* key, int len, int nodePos = 0)
+        {
+            //if (this.encoding == Encoding.Unicode)
+            //    return this.da.ExactMatchSearch((byte*)key, len, nodePos);
+
+            //エンコード
+            int maxByteCount = this.encoding.GetMaxByteCount(len);
+            byte* bytes = stackalloc byte[maxByteCount];
+            int bytesLen = this.encoding.GetBytes(key, len, bytes, maxByteCount);
+
+            DoubleArray.ResultPair result = this.da.ExactMatchSearch(bytes, bytesLen, nodePos);
+
+            //文字数をデコードしたものに変換
+            result.Length = this.encoding.GetCharCount(bytes, result.Length);
+
+            return result;
+        }
+
+        public unsafe int CommonPrefixSearch(char* key, int len, DoubleArray.ResultPair* result, int rLen)
+        {
+            //if (this.encoding == Encoding.Unicode)
+            //    return this.da.CommonPrefixSearch((byte*)key, result, rLen, len);
+
+            //エンコード
+            int maxByteLen = this.encoding.GetMaxByteCount(len);
+            byte* bytes = stackalloc byte[maxByteLen];
+            int bytesLen = this.encoding.GetBytes(key, len, bytes, maxByteLen);
+
+            int n = this.da.CommonPrefixSearch(bytes, result, rLen, bytesLen);
+
+            //文字数をデコードしたものに変換
+            for (int i = 0; i < n; i++)
+                result[i].Length = this.encoding.GetCharCount(bytes, result[i].Length);
+
+            return n;
+        }
+
+        #endregion
+
+        #region Get Infomation
+
+        public unsafe Token[] GetToken(DoubleArray.ResultPair n)
+        {
+            Token[] dist = new Token[0xFF & n.Value];
+            int tokenPos = n.Value >> 8;
+#if MMF_DIC
+            this.tokens.ReadArray<Token>(tokenPos * sizeof(Token), dist, 0, dist.Length);
+#else
+            Array.Copy(this.tokens, tokenPos, dist, 0, dist.Length);
+#endif
+            return dist;
+        }
+
+        public string GetFeature(uint featurePos)
+        {
+            return StrUtils.GetString(this.features, (long)featurePos, this.encoding);
+        }
+
+        #endregion
+
+        #region etc.
+
+        public bool IsCompatible(MeCabDictionary d)
+        {
+            return (this.Version == d.Version &&
+                    this.LSize == d.LSize &&
+                    this.RSize == d.RSize &&
+                    this.CharSet == d.CharSet);
+        }
+
+        #endregion
+
+        #region Dispose
+
+        private bool disposed;
+
+        /// <summary>
+        /// 使用されているリソースを開放する
+        /// </summary>
+        public void Dispose()
+        {
+            this.Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposed) return;
+
+            if (disposing)
+            {
+                if (this.da != null) this.da.Dispose();
+#if MMF_DIC
+                if (this.mmf != null) this.mmf.Dispose();
+                if (this.tokens != null) this.tokens.Dispose();
+                if (this.features != null) this.features.Dispose();
+#endif
+            }
+
+            this.disposed = true;
+        }
+
+        ~MeCabDictionary()
+        {
+            this.Dispose(false);
+        }
+
+        #endregion
+    }
+}
index b73333f..da7a6d2 100644 (file)
-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-#if MMF_DIC\r
-using System.IO.MemoryMappedFiles;\r
-#endif\r
-\r
-namespace NMeCab.Core\r
-{\r
-    public static class StrUtils\r
-    {\r
-        private const byte Nul = (byte)0;\r
-\r
-        /// <summary>\r
-        /// バイト配列の中から終端が\0で表された文字列を取り出す。\r
-        /// </summary>\r
-        /// <remarks>\r
-        /// バイト配列の長さはInt32.MaxValueを超えていても良い。\r
-        /// </remarks>\r
-        /// <param name="bytes">バイト配列</param>\r
-        /// <param name="enc">文字エンコーディング</param>\r
-        /// <returns>文字列(\0は含まない)</returns>\r
-        public static string GetString(byte[] bytes, Encoding enc)\r
-        {\r
-            return StrUtils.GetString(bytes, 0L, enc);\r
-        }\r
-\r
-        /// <summary>\r
-        /// バイト配列の中から終端が\0で表された文字列を取り出す。\r
-        /// </summary>\r
-        /// <remarks>\r
-        /// バイト配列の長さはInt32.MaxValueを超えていても良い。\r
-        /// </remarks>\r
-        /// <param name="bytes">バイト配列</param>\r
-        /// <param name="offset">オフセット位置</param>\r
-        /// <param name="enc">文字エンコーディング</param>\r
-        /// <returns>文字列(\0は含まない)</returns>\r
-        public unsafe static string GetString(byte[] bytes, long offset, Encoding enc)\r
-        {\r
-            fixed (byte* pBytes = bytes)\r
-                return StrUtils.GetString(pBytes + offset, enc);\r
-        }\r
-\r
-        /// <summary>\r
-        /// バイト配列の中から終端が\0で表された文字列を取り出す。\r
-        /// </summary>\r
-        /// <remarks>\r
-        /// バイト配列の長さはInt32.MaxValueを超えていても良い。\r
-        /// </remarks>\r
-        /// <param name="bytes">デコードする最初のバイトへのポインタ</param>\r
-        /// <param name="enc">文字エンコーディング</param>\r
-        /// <returns>文字列(\0は含まない)</returns>\r
-        public unsafe static string GetString(byte* bytes, Encoding enc)\r
-        {\r
-            //バイト長のカウント\r
-            int byteCount = 0;\r
-            while (*bytes != Nul) //終端\0に到達するまでシーク\r
-            {\r
-                checked { byteCount++; } //文字列のバイト長がInt32.MaxValueを超えたならエラー\r
-                bytes++;\r
-            }\r
-            bytes -= byteCount;\r
-\r
-            //生成されうる最大文字数のバッファを確保\r
-            int maxCharCount = enc.GetMaxCharCount(byteCount);\r
-            fixed (char* buff = new char[maxCharCount])\r
-            {\r
-                //バイト配列を文字列にデコード\r
-                int len = enc.GetChars(bytes, byteCount, buff, maxCharCount);\r
-                return new string(buff, 0, len);\r
-            }\r
-        }\r
-\r
-#if MMF_DIC\r
-\r
-        /// <summary>\r
-        /// MemoryMappedViewAccessorから終端が\0で表された文字列を取り出す。\r
-        /// </summary>\r
-        /// <remarks>\r
-        /// MemoryMappedViewAccessorの容量はInt32.MaxValueを超えていても良い。\r
-        /// </remarks>\r
-        /// <param name="accessor">MemoryMappedViewAccessor</param>\r
-        /// <param name="index">オフセット位置</param>\r
-        /// <param name="enc">文字エンコーディング</param>\r
-        /// <param name="buffSize">内部で使用するバッファの初期サイズ</param>\r
-        /// <returns>文字列(\0は含まない)</returns>\r
-        public static string GetString(MemoryMappedViewAccessor accessor, long offset, Encoding enc,\r
-                                        int buffSize = 128)\r
-        {\r
-            byte[] buff = new byte[buffSize]; //IO回数削減のためのバッファ配列\r
-            accessor.ReadArray<byte>(offset, buff, 0, buffSize); //初期読込\r
-\r
-            //バイト長のカウント\r
-            int byteCount = 0;\r
-            while (buff[byteCount] != Nul) //終端\0に到達するまでシーク\r
-            {\r
-                byteCount++;\r
-\r
-                if (byteCount == buffSize) //バッファ配列の終端\r
-                {\r
-                    //バッファ配列の拡張と追加読込\r
-                    checked { buffSize *= 2; } //Int32.MaxValueを超えたならエラー\r
-                    byte[] newBuff = new byte[buffSize];\r
-                    Buffer.BlockCopy(buff, 0, newBuff, 0, byteCount);\r
-                    accessor.ReadArray<byte>(offset + byteCount, newBuff, byteCount, buffSize - byteCount);\r
-                    buff = newBuff;\r
-                }\r
-            }\r
-\r
-            //バッファ配列を文字列にデコード\r
-            return enc.GetString(buff, 0, byteCount);\r
-        }\r
-\r
-#endif\r
-\r
-    }\r
-}\r
+using System;
+using System.Collections.Generic;
+using System.Text;
+#if MMF_DIC
+using System.IO.MemoryMappedFiles;
+#endif
+
+namespace NMeCab.Core
+{
+    public static class StrUtils
+    {
+        private const byte Nul = (byte)0;
+
+        /// <summary>
+        /// バイト配列の中から終端が\0で表された文字列を取り出す。
+        /// </summary>
+        /// <remarks>
+        /// バイト配列の長さはInt32.MaxValueを超えていても良い。
+        /// </remarks>
+        /// <param name="bytes">バイト配列</param>
+        /// <param name="enc">文字エンコーディング</param>
+        /// <returns>文字列(\0は含まない)</returns>
+        public static string GetString(byte[] bytes, Encoding enc)
+        {
+            return StrUtils.GetString(bytes, 0L, enc);
+        }
+
+        /// <summary>
+        /// バイト配列の中から終端が\0で表された文字列を取り出す。
+        /// </summary>
+        /// <remarks>
+        /// バイト配列の長さはInt32.MaxValueを超えていても良い。
+        /// </remarks>
+        /// <param name="bytes">バイト配列</param>
+        /// <param name="offset">オフセット位置</param>
+        /// <param name="enc">文字エンコーディング</param>
+        /// <returns>文字列(\0は含まない)</returns>
+        public unsafe static string GetString(byte[] bytes, long offset, Encoding enc)
+        {
+            fixed (byte* pBytes = bytes)
+                return StrUtils.GetString(pBytes + offset, enc);
+        }
+
+        /// <summary>
+        /// バイト配列の中から終端が\0で表された文字列を取り出す。
+        /// </summary>
+        /// <remarks>
+        /// バイト配列の長さはInt32.MaxValueを超えていても良い。
+        /// </remarks>
+        /// <param name="bytes">デコードする最初のバイトへのポインタ</param>
+        /// <param name="enc">文字エンコーディング</param>
+        /// <returns>文字列(\0は含まない)</returns>
+        public unsafe static string GetString(byte* bytes, Encoding enc)
+        {
+            //バイト長のカウント
+            int byteCount = 0;
+            while (*bytes != Nul) //終端\0に到達するまでシーク
+            {
+                checked { byteCount++; } //文字列のバイト長がInt32.MaxValueを超えたならエラー
+                bytes++;
+            }
+            bytes -= byteCount;
+
+            //生成されうる最大文字数のバッファを確保
+            int maxCharCount = enc.GetMaxCharCount(byteCount);
+            fixed (char* buff = new char[maxCharCount])
+            {
+                //バイト配列を文字列にデコード
+                int len = enc.GetChars(bytes, byteCount, buff, maxCharCount);
+                return new string(buff, 0, len);
+            }
+        }
+
+#if MMF_DIC
+
+        /// <summary>
+        /// MemoryMappedViewAccessorから終端が\0で表された文字列を取り出す。
+        /// </summary>
+        /// <remarks>
+        /// MemoryMappedViewAccessorの容量はInt32.MaxValueを超えていても良い。
+        /// </remarks>
+        /// <param name="accessor">MemoryMappedViewAccessor</param>
+        /// <param name="index">オフセット位置</param>
+        /// <param name="enc">文字エンコーディング</param>
+        /// <param name="buffSize">内部で使用するバッファの初期サイズ</param>
+        /// <returns>文字列(\0は含まない)</returns>
+        public static string GetString(MemoryMappedViewAccessor accessor, long offset, Encoding enc,
+                                        int buffSize = 128)
+        {
+            byte[] buff = new byte[buffSize]; //IO回数削減のためのバッファ配列
+            accessor.ReadArray<byte>(offset, buff, 0, buffSize); //初期読込
+
+            //バイト長のカウント
+            int byteCount = 0;
+            while (buff[byteCount] != Nul) //終端\0に到達するまでシーク
+            {
+                byteCount++;
+
+                if (byteCount == buffSize) //バッファ配列の終端
+                {
+                    //バッファ配列の拡張と追加読込
+                    checked { buffSize *= 2; } //Int32.MaxValueを超えたならエラー
+                    byte[] newBuff = new byte[buffSize];
+                    Buffer.BlockCopy(buff, 0, newBuff, 0, byteCount);
+                    accessor.ReadArray<byte>(offset + byteCount, newBuff, byteCount, buffSize - byteCount);
+                    buff = newBuff;
+                }
+            }
+
+            //バッファ配列を文字列にデコード
+            return enc.GetString(buff, 0, byteCount);
+        }
+
+#endif
+
+        /// <summary>
+        /// 指定の名前に対応するエンコーディングを取得する(.NET FWが対応していない名前にもアドホックに対応)
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public static Encoding GetEncoding(string name)
+        {
+            switch (name.ToUpper())
+            {
+                case "UTF8":
+                    return Encoding.UTF8;
+                default:
+                    return Encoding.GetEncoding(name);
+            }
+        }
+    }
+}