//*****************************************************************************
// ReplaceStrUniFast.cpp : 指定の文字列中に指定の文字列があるか否かチェックして、
//                          あれば、指定の文字列で置き換えた文字列を戻す。
//*****************************************************************************

#include "stdafx.h"

CString ReplaceStrUniFast( CString& ostr , CString& findstr , CString& newstr , int* presult ) ;
BYTE* SearchTextSimple( BYTE* hStartP , int blen , LPCSTR lpszFind, BOOL bNext, BOOL bCase ) ;

//*****************************************************************************
// 機能 :指定の文字列中に指定の文字列があるか否かチェックして、
//          あれば、指定の文字列で置き換えた文字列を戻す。
//  戻り値:*presult=TRUE:置き換えた, FALSE:指定の文字列はない
//  注意  :
//*****************************************************************************
CString ReplaceStrUniFast( CString& ostr , CString& findstr , CString& newstr , int* presult )
{
    *presult = FALSE ;

    int olen = ostr.GetLength( ) ;
    if ( olen == 0 )
        return ostr ;

    int flen = findstr.GetLength( ) ;
    if ( flen == 0 )
        return ostr ;

    BYTE* obuf = (BYTE*)(const char*)ostr ;

    int newlen = newstr.GetLength( ) ;

    CString tstr = "" ;

    int tlen = olen * 2 + (20 * 1024) ;                 // このサイズを越える場合には、++方式へ移行!!!
    BYTE* tbuf = (BYTE*)tstr.GetBuffer( tlen+100 ) ;    // 解放を忘れるな!!!

    int bOver = FALSE ;
    int bReplaced = FALSE ;
    int i ;
    int k ; 
    for ( i = 0 , k = 0 ; i < olen ; )
    {
        BYTE* pb = SearchTextSimple( &obuf[i] , olen-i , (const char*)findstr , TRUE , FALSE ) ;
        if ( pb == NULL )
            break ;

        bReplaced = TRUE ;

        int pos = (int)(pb - obuf ) ;

        int len = pos - i ;

        if ( bOver )
        {
            tstr += ostr.Mid( i , len ) ;
            tstr += newstr ;

        }
        else
        {
            CString wstr = ostr.Mid( i , len ) ;
            int wlen = wstr.GetLength( ) ;

            if ( k + wlen + newlen >= tlen )
            {
                ASSERT( FALSE ) ;           // ここに来ることの確認用!!!

                tstr.ReleaseBuffer( k ) ;   // 解放を忘れるな!!!

                tstr += wstr ;
                tstr += newstr ;

                bOver = TRUE ;

            }
            else
            {
                memcpy( &tbuf[k] , (const char*)wstr , wlen ) ; 
                k += wlen ;

                memcpy( &tbuf[k] , (const char*)newstr , newlen ) ; 
                k += newlen ;

            }

        }

        i = pos + flen ;

    }

    if ( !bOver )
        tstr.ReleaseBuffer( k ) ;           // 解放を忘れるな!!!

    if ( i < olen )
        tstr += ostr.Mid( i , olen-i ) ;

    *presult = bReplaced ;

    return tstr ;

}

//*****************************************************************************
// 機能 : 指定範囲の中で文字列を検索する。
//  戻り値: 見つかった文字列位置へのポインタ、NULLのときは見つからなかったことを意味する。
//*****************************************************************************
BYTE* SearchTextSimple( BYTE* hStartP , int blen , LPCSTR lpszFind, BOOL bNext, BOOL bCase )
{
    int ret ;
    BYTE* hpszFound ;

    hpszFound = NULL ;
    UINT nLenSearch = lstrlen(lpszFind);

    ASSERT( nLenSearch > 0 ) ;          // 0 だと != NULLで戻ってしまう?!!! 

    int  nChFind ;
    if ( _ismbblead( (BYTE)(*lpszFind) ) )
        nChFind = 2 ;
    else
        nChFind = 1 ;

    BYTE* hStopP = hStartP + blen - nLenSearch + 1 ;
    if ( hStartP >= hStopP || blen < nChFind )
        return NULL ;

    BYTE* hpsz = hStartP ;
    BYTE* hpszStop = hStopP ;
    
    for ( ; hpsz < hpszStop ; )
    {
        if ( bCase )
            ret = memcmp( (BYTE*)hpsz , lpszFind , nChFind ) ;
        else
            ret = _mbsnbicmp( (const BYTE*)hpsz , (const BYTE*)lpszFind , nChFind ) ;

        if ( ret == 0 )
        {
            if ( bCase )
                ret = memcmp( (BYTE*)hpsz , lpszFind , nLenSearch ) ;
            else
                ret = _mbsnbicmp( (const BYTE*)hpsz , (const BYTE*)lpszFind , nLenSearch ) ;

            if ( ret == 0 )
            {
                hpszFound = hpsz ;
                if ( bNext )
                    break ;
            }
        }

        if ( _ismbblead( (BYTE)(*hpsz) ) )
            hpsz += 2 ;
        else
            hpsz += 1 ;
    }
    return hpszFound ;
}


//*****************************************************************************
// ReplaceStrUniFast.cpp : Ver1.00  2006/12/29
// Example :
//  CString ostr = "1234567890abc 1234567890abc" ;
//  CString findstr = "56" ;
//  CString newstr = "<56>" ;
//  int result ;
//  CString tstr = ReplaceStrUniFast( ostr , findstr , newstr , &result ) ;
//
// Copyright(C) Edcom Inc. (http://www.edcom.jp/) All rights reserved. 
//*****************************************************************************