HMJRE.dll の使い方についてNo.28750
black さん 10/08/06 05:26
 
お世話になります。

HMJRE.dll 内の各関数を使用する際の手続きについて、
以下のような認識で問題ないでしょうか。
-----------------------------------------
A. オープン処理(Fuzzy_Open,Jre2Open)

B. あいまい検索に設定、コンパイルの実行

C. コンバート

D. 検索実行

E. 解放処理(Jre2Close,Fuzzy_Close)
-----------------------------------------

「検索対象文字列」と「検索文字列」が同一の場合は D の検索実行を
複数回呼び出すことで実現可能ですが、

"検索対象文字列を変更する場合"は E、A の手順を踏まずに D の状態が終了したま
ま B に進むことは仕様の範囲内でしょうか?

今まではこのような使い方をしていて問題がなかったのですが、特定のケースで結果
が異なる現象が確認出来たので、そもそもの仕様を確認したかった次第です。

どうぞよろしくお願いいたします。

[ ]
RE:28750 HMJRE.dll の使い方についてNo.28751
秀まるお2 さん 10/08/06 09:05
 
 そういう認識でいいはずです。

 同じ検索文字列で繰り返し検索する場合には、

        Fuzzy_ConvertTarget
        Fuzzy_RealPos2FindPos
        JreGetMatchInfo
        Fuzzy_FindArea2RealArea

 を呼び出すのを繰り返すだけになります。CompileやOpen/Closeを毎回呼んだ
ら多少遅くなります。

> 今まではこのような使い方をしていて問題がなかったのですが、特定のケースで結果
> が異なる現象が確認出来たので、そもそもの仕様を確認したかった次第です。

 JRE2構造体の中のnStartの値が違うことによって結果が違ってるだけとか?

 参考までに、秀丸メールの中にある検索の処理のソースコードを一部(繰り返
し呼び出す部分の処理)掲載します。

BOOL FINDPACK::JreGetMatchInfo( char* pszBuffer, int cchBuffer ) {
    if( szFind[0] == '\0' ) {
        return FALSE;
    }
    BOOL    fHmFuzzy = fFuzzy && pfnFuzzy_Open != NULL;
    int     nStartOrigin = jredata.nStart;
    BOOL    fWordFuzzyMatch = FALSE;
    if( fHmFuzzy ) {
        pfnFuzzy_ConvertTarget( &fuzzydata, pszBuffer );
        pszBuffer = fuzzydata.pszTargetConved;
        cchBuffer = (int)strlen(pszBuffer);
        jredata.nStart = pfnFuzzy_RealPos2FindPos( &fuzzydata, nStartOrigin );
        fWordFuzzyMatch = fWordOnly;
    }
    BOOL    fFound;
    if( !fFindEachLine ) {
        fFound = pfnJreGetMatchInfo_V318( &jredata, pszBuffer, cchBuffer, fW
ordFuzzyMatch, &fuzzydata );
    } else {
        fFound = FALSE;
        // fFindEachLineの場合の処理。cCRInSearch + 1行づつ検索しないといけ
ない。面倒!
        ...
        ... (省略)
        ...
    }
    if( fHmFuzzy ) {
        jredata.nStart = nStartOrigin;
        if( fFound ) {
            jredata.nPosition = pfnFuzzy_FindArea2RealArea( &fuzzydata, jred
ata.nPosition, (int*)&jredata.nLength );
        }
    }
    return fFound;
}

[ ]
RE:28751 HMJRE.dll の使い方についてNo.28761
black さん 10/08/06 14:55
 
秀まるお2 さん

お返事ありがとうございます。

> JRE2構造体の中のnStartの値が違うことによって結果が違ってるだけとか?
nStart は、文字列を変える場合は毎回手動で 0 に設定しております。
今回デバッガを使い、jre2 / JREFUZZYDATA 構造体の各変数を確認しても、私自身の
設定ミスなどが理解している範囲では考えられなかった為、質問させていただきまし
た。

動作としては、何かしらのキャッシュが残ってるためと感じています。


以下の様な文字列に対して後方参照を行うと、発生が確認できました。

まず成功のパターンを書きます。
( 初期化は省いてます、またプログラムコードなので \ が各所入っています )

----------------------------------------------
1.

// 【A】コンパイル
Compile( "(<dt>[^<]*)(<font color=\"[^\"]*\"><b>)([^<]*)(<a href=\"mailto:[^
\"]*\">)*([^>]+)(</a>)*(</b></font>)(.+$)");

// 【B】検索( Find の最初では nStart は 0 にします )
Find( "<dt>343 :<font color=\"green\"><B>名無し</b></font>:2000/01/01(金)
20:16:17 ID:xxxxxxxx<dd> てすと <br> てすと <br><br>" );

// 【C】4番目の後方参照を得る →この場合、見つからない事が目的
int area=0, pos, realpos;
pos = JreGetTagPosition( &jre2, '4', &area );
realpos = fy_Fuzzy_FindPos2RealPos( &fuzy, pos );
if( realpos!=-1 ){
  Fuzzy_FindArea2RealArea( &fuzy, pos, &area );
}

// 【D】4番目の要素 <a href=... は見つからないので、範囲外の値が返却される。
printf( "%d : %d\n", realpos, area );
-----------------------------------------------

そして上記を実施する前に、以下に記載する文字列で「コンパイル&検索」を実施す
ると、
上記での後方参照で得られる範囲が変わってしまいます。


2.
// 【A】コンパイル(先ほどと、全く同等の値です)
Compile( ... );

// 【B】検索( mailto: が含んでる場合です )
Find( "<dt>9 :<font color=\"green\"><B><A HREF=\"mailto:sage\">1</A></b></f
ont>:2000/01/01(金) 22:29:36 ID:xxxxxxxx<dd> ほげほげ<br><br>" );


ここでは 【C】【D】 は期待通りの値です。2の一連の作業を実施した後、

1の手続き【A】【B】【C】【D】を踏むと、1での「後方参照」で得られる値が
変化します。
 ( なお2以外の、ヒットしない文字列を与えた場合は問題ありません )

秀丸オプションとしては FUZZYOPTION_NOSPACE は OFF にしており、
それ以外はデフォルト値です。


まとめると、

以下のフローで「正規表現検索」した場合、1C で得られる「後方参照値」が
2A 〜 2D を "実施したかどうかにより" 変化します。


  【2A】→【2B】→【2C】→【2D】→

  【1A】→【1B】→【1C】→【1D】


2A で与えている「検索対象文字列」を一致させない場合は、
期待通りの後方参照値が返って来ます。


長ったらしくなってしまい申し訳ございません。


> そういう認識でいいはずです。
>
> 同じ検索文字列で繰り返し検索する場合には、
>
>        Fuzzy_ConvertTarget
>        Fuzzy_RealPos2FindPos
>        JreGetMatchInfo
>        Fuzzy_FindArea2RealArea
>
> を呼び出すのを繰り返すだけになります。CompileやOpen/Closeを毎回呼んだ
>ら多少遅くなります。
>
>> 今まではこのような使い方をしていて問題がなかったのですが、特定のケースで結果
>> が異なる現象が確認出来たので、そもそもの仕様を確認したかった次第です。
>
> JRE2構造体の中のnStartの値が違うことによって結果が違ってるだけとか?
>
> 参考までに、秀丸メールの中にある検索の処理のソースコードを一部(繰り返
>し呼び出す部分の処理)掲載します。
>
>BOOL FINDPACK::JreGetMatchInfo( char* pszBuffer, int cchBuffer ) {
>    if( szFind[0] == '\0' ) {
>        return FALSE;
>    }
>    BOOL    fHmFuzzy = fFuzzy && pfnFuzzy_Open != NULL;
>    int     nStartOrigin = jredata.nStart;
>    BOOL    fWordFuzzyMatch = FALSE;
>    if( fHmFuzzy ) {
>        pfnFuzzy_ConvertTarget( &fuzzydata, pszBuffer );
>        pszBuffer = fuzzydata.pszTargetConved;
>        cchBuffer = (int)strlen(pszBuffer);
>        jredata.nStart = pfnFuzzy_RealPos2FindPos( &fuzzydata, nStartOrigin );
>        fWordFuzzyMatch = fWordOnly;
>    }
>    BOOL    fFound;
>    if( !fFindEachLine ) {
>        fFound = pfnJreGetMatchInfo_V318( &jredata, pszBuffer, cchBuffer, f
>WordFuzzyMatch, &fuzzydata );
>    } else {
>        fFound = FALSE;
>        // fFindEachLineの場合の処理。cCRInSearch + 1行づつ検索しないといけ
>ない。面倒!
>        ...
>        ... (省略)
>        ...
>    }
>    if( fHmFuzzy ) {
>        jredata.nStart = nStartOrigin;
>        if( fFound ) {
>            jredata.nPosition = pfnFuzzy_FindArea2RealArea( &fuzzydata, jre
>data.nPosition, (int*)&jredata.nLength );
>        }
>    }
>    return fFound;
>}

[ ]
RE:28761 HMJRE.dll の使い方についてNo.28766
秀まるお2 さん 10/08/06 16:30
 
 詳しい情報ありがとうございます。

 まだちょっと再現テストは出来てないというか、再現テストするためには再現
用のプログラムを作らないとダメなのでまだやってないんですけども…。

 正規表現パターンで、\4に相当する部分が、

    (<a href="mailto:[^"]*">)*

 のように、長さが0にマッチするようなパターンを使っているがために、もし
もそこにヒットしない場合に、タグへのマッチ位置が初期化されなくて、それで
おかしくなってしまってるような気がします。

 これはこれでバグと言われればバグのような気がします。

 秀丸エディタ/秀丸メールの場合だと、GetTagPosition相当の関数を呼び出す
のは置換の時だけなので、結果、それを呼んだ後にすぐさま次ぎの
Jre2GetMatchInfo呼び出しをすることは無いので、結果としてバグが表に出てな
いということなのかなぁと思います。

 ということで、これはこれでもうちょっと詳しく、まずは再現テスト用のプロ
グラムを作るなどしてみます。

---------------------------------------------------
 とりあえずの回避策ですけども、

    (<a href="mailto:[^"]*">)*

 の所を、

    ((<a href="mailto:[^"]*">)*)

 のように書いていただければ回避出来るのではないかと思います。そういう風
に書いていただいた方がより正確にタグの位置を指定する意味にもなるかなぁと
いう気もするしということで…。

[ ]
RE:28766 HMJRE.dll の使い方についてNo.28769
秀まるお2 さん 10/08/06 16:43
 
 再現用のプログラムを作るまでもなく、デバッガーでトレースしながら変数を
手で書き換える等して再現できました。

 たしかに、タグヒットした位置を覚えておく変数の初期化が抜けてまして、ま
ったくヒットしないタグについては、前回のJre2GetMatchInfoにてヒットした値
がそのまま返ってしまってました。

 (pattern)*  とかのケースでまったくヒットしないケースがあることを想定し
てませんでした。

 大変失礼しました。

 ということでさっそく修正させていただきます。

 アップロード出来るようになったらまた連絡させていただきます。

[ ]
RE:28769 HMJRE.dll の使い方についてNo.28776
black さん 10/08/06 19:10
 
秀まるお2 さん

お返事ありがとうございます。

なるほど、返却される値がおかしいのはキャッシュが残ってる(初期化が抜けている)
という事ですね。

修正して頂けるようで大変嬉しいです。

またご提示頂いた回避策の方も、

>>    (<a href="mailto:[^"]*">)*
>> の所を、
>>    ((<a href="mailto:[^"]*">)*)

正規表現の知識として参考にさせて頂きました。この場合 () で二重でに囲ってるの
ですが後方参照としては、そのまま \4 になるのですね。
 ( ()の分だけ以降は、後方参照の数字がズレるのかと思いました )

この様な指定が可能だとは知りませんでした。


> 再現用のプログラムを作るまでもなく、デバッガーでトレースしながら変数を
≪全文引用されていたのでコミュニテックス会議室システムが引用部分を省略処理し
ました。≫
> アップロード出来るようになったらまた連絡させていただきます。

[ ]
RE:28776 HMJRE.dll の使い方についてNo.28784
秀まるお2 さん 10/08/09 13:06
 
 秀丸エディタV8.01aということで、HmJre.dllだけ差し替えた秀丸エディタを
アップロードさせていただきました。

 ということでお願いします。

[ ]
RE:28784 HMJRE.dll の使い方についてNo.28788
black さん 10/08/09 19:41
 
ご対応頂きありがとうございます。

早速同一ソース上で確認した所、

  JreGetTagPosition()

の戻り値が、Compile()/Find() 2回目以降でも期待通り -1 と返ってきており、

特定の後方参照が存在しなかった場合( 今回の場合は \4, \6 )は
"正しく取得できないこと" が確認取れました。


これで Open/Close() を毎度呼ばずに、連続して検索出来そうです。


素早いご対応に感謝感激です。ありがとうございました。

> 秀丸エディタV8.01aということで、HmJre.dllだけ差し替えた秀丸エディタを
>アップロードさせていただきました。
>
> ということでお願いします。

[ ]