-// 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
+ }
+}
-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);
+ }
+ }
+ }
+}