/// <summary> /// BoMatch()呼び出し/結果処理簡略化 /// </summary> /// <param name="pattern">検索パターン(NULLを指定すると、前回のコンパイル済みパターンを使用する)</param> /// <param name="options">オプション</param> /// <param name="input">検索対象文字列</param> /// <param name="targetstart">検索開始文字位置</param> /// <param name="targetend">検索終了文字位置</param> /// <param name="one_shot">ワンショットモード:通常はfalseを指定</param> /// <returns>検索によって見つかった Matched オブジェクト</returns> protected Matched BoMatch( string pattern, string options, string input, int targetstart, int targetend, bool one_shot) { if (this.disposed) { throw new ObjectDisposedException("BregonigRegexオブジェクト"); } lock (this.pattern) { // 検索位置をポインタに変換 AllocText(input); IntPtr targetstartp = IntPtr.Add(strstartp, targetstart * sizeof(char)); IntPtr targetendp = IntPtr.Add(strstartp, targetend * sizeof(char)); StringBuilder msgSb = new StringBuilder(80); // エラーメッセージ格納用領域を確保 int ret = BoMatch(pattern, options, strstartp, targetstartp, targetendp, one_shot, ref rxp, msgSb); if (ret < 0) { // エラーあり throw new ArgumentException(msgSb.ToString()); } if (ret > 0) { // マッチあり:構造体ポインタの最新の内容を取り出し BREGEXP rx = (BREGEXP)(Marshal.PtrToStructure(rxp, typeof(BREGEXP))); int arrayLength = rx.nparens + 1; // グループ数+[0]マッチ箇所全体 の分 Group[] groups = new Group[arrayLength]; for (int i = 0; i < arrayLength; i++) { groups[i] = rx.CreateGroup(i, this); } return(new Matched(groups, this, targetstart, targetend)); } else { return(null); } } }
/// <summary> /// BoSubst()呼び出し/結果処理簡略化 /// </summary> /// <param name="subst">置換パターン(NULLを指定すると、前回のコンパイル済みパターンを使用する)</param> /// <param name="options">オプション</param> /// <param name="input">検索対象文字列</param> /// <param name="targetstart">検索開始文字位置</param> /// <param name="targetend">検索終了文字位置</param> /// <param name="match">置換対象となるMatchedオブジェクト</param> /// <returns>置換結果文字列(matchが指定されている場合はマッチした部分の変更結果、matchがnullの場合はinput全体の置換結果)</returns> protected string BoSubst( string subst, string options, string input, int targetstart, int targetend, Matched match = null) { if (this.disposed) { throw new ObjectDisposedException("BregonigRegexオブジェクト"); } // 置換オプション/置換パターンが前回と一緒であればコンパイルを省略する string pattern = this.pattern; if (options == this.prevoptions) { pattern = null; options = null; if (subst == this.prevsubst) { subst = null; } else { // subst相違あり、今回指定されたsubstを保存 this.prevsubst = subst; } } else { // option相違あり、今回指定されたoptionsとsubstを保存 this.prevoptions = options; this.prevsubst = subst; } lock (this.pattern) { // 検索位置をポインタに変換 AllocText(input); IntPtr targetstartp = IntPtr.Add(strstartp, targetstart * sizeof(char)); IntPtr targetendp = IntPtr.Add(strstartp, targetend * sizeof(char)); StringBuilder msgSb = new StringBuilder(80); // エラーメッセージ格納用領域を確保 int ret = BoSubst(pattern, subst, options, strstartp, targetstartp, targetendp, null, ref rxp, msgSb); if (ret < 0) { // エラーあり throw new ArgumentException(msgSb.ToString()); } if (ret > 0) { // 置換成功:構造体ポインタの最新の内容を取り出し BREGEXP rx = (BREGEXP)(Marshal.PtrToStructure(rxp, typeof(BREGEXP))); if (match != null) { Group replacedMatch = rx.CreateGroup(0, this); // 置換された部分のマッチ情報を取得 if (match.Index != replacedMatch.Index || match.Length != replacedMatch.Length) { // 検索時/置換時でマッチ箇所が同一にならなかった(通常発生しない。発生したらBregonigRegexのバグ、要究明) throw new SystemException("置換対象のマッチ箇所(Index=" + match.Index + ", Match=" + match.Length + ")" + "とは異なる箇所(Index=" + replacedMatch.Index + ", Match=" + replacedMatch.Length + ")が置換されました。"); } if (rx.outp == null) { return(string.Empty); // 置換結果が空文字となった } // 置換部分の開始位置=置換結果全体の開始位置+(マッチ箇所の開始位置、ただし探索開始位置考慮) IntPtr replacedstart = IntPtr.Add(rx.outp, (match.Index - targetstart) * sizeof(char)); // 置換部分の置換後文字列長=マッチ箇所の置換前文字列長+置換結果全体の文字列長-置換前文字列全体の文字列長 int len = match.Length + (int)((rx.outendp.ToInt64() - rx.outp.ToInt64()) / sizeof(char)) - (targetend - targetstart); // 置換部分の文字列内容のみをピンポイントで抜き出す return(Marshal.PtrToStringUni(replacedstart, len)); } else { // 置換後文字列全体を組み立て StringBuilder sb = new StringBuilder(); if (targetstart > 0) { sb.Append(input.Substring(0, targetstart)); } if (rx.outp != null) { // 空文字列に置換されていなければ、置換結果の文字列を取り出し int len = (int)((rx.outendp.ToInt64() - rx.outp.ToInt64()) / sizeof(char)); sb.Append(Marshal.PtrToStringUni(rx.outp, len)); } if (targetend < input.Length) { sb.Append(input.Substring(targetend)); } return(sb.ToString()); } } else { // 置換箇所なし if (match != null) { // 検索時/置換時でマッチ箇所が同一にならなかった(通常発生しない。発生したらBregonigRegexのバグ、要究明) throw new SystemException("置換対象のマッチ箇所(Index=" + match.Index + ", Match=" + match.Length + ")が検出できませんでした。"); } // 置換前テキスト内容のまま変更なし return(input); } } }