Home

Resume

Blog

Teikitu


// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//  »Project«   Teikitu Gaming System (TgS) (∂)
//  »File«      TgS Common - Util SP - String.c
//  »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  »Version«   4.0
// ------------------------------------------------------------------------------------------------------------------------------ //
//  Copyright: © 2002-2010, Andrew Aye.  All Rights Reserved.
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //

#include <string.h>


// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  File Local Functions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

TgFORCEINLINE P_TgCHAR tgCM_UTS_ST_Get_Buffer( PCU_STg2_UTS_ST );
TgFORCEINLINE TgVOID tgCM_UTS_ST_Null_Term( PCU_STg2_UTS_ST, C_TgUINT32 );
TgFORCEINLINE TgBOOL tgCM_UTS_ST_Overlap( CPC_TgVOID, C_TgSIZE, CPC_TgVOID, C_TgSIZE );




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Public Functions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

TgVOID tgCM_UTS_ST_CH_Assign( PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiCount, C_TgCHAR uiChar )
{
    if (TgEXPECT_FALSE(!(0 != uiCount && TgT('\0') != uiChar)))
    {
        tgCM_UTS_ST_Clear( ptgDest );
    }
    else
    {
        C_TgUINT32                          uiNew_Reserve = uiCount + 1;
        P_TgCHAR                            pszDest;
    #if TgS_WIDE_CHAR
        TgUINT32                            uiIndex;
    #endif

        if (uiNew_Reserve == ptgDest->m_uiReserve)
        {
            pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
        }
        else if (uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
        {
            if (ptgDest->m_uiReserve > ETgSTRING_STATIC_BUFFER_SIZE)
            {
                TgFREE_POOL( tgCM_UTS_ST_Get_Buffer( ptgDest ) );
                ptgDest->m_uiReserve = ETgSTRING_STATIC_BUFFER_SIZE;
            };
            pszDest = ptgDest->m_unData.m_aBuffer;
        }
        else
        {
            pszDest = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

            if (TgEXPECT_FALSE(0 == pszDest))
            {
                TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_CH_Assign") );
                tgCM_UTS_ST_Clear( ptgDest );
                return;
            };

            tgCM_UTS_ST_Clear( ptgDest );
            ptgDest->m_unData.m_pszDest = pszDest;
            ptgDest->m_uiReserve = uiNew_Reserve;
        };

    #if TgS_WIDE_CHAR
        for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
        {
            pszDest[uiIndex] = uiChar;
        };
    #else
        memset( pszDest, uiChar, uiCount );
    #endif
        tgCM_UTS_ST_Null_Term( ptgDest, uiCount );
    };
}


TgVOID tgCM_UTS_ST_SF_Assign(
    PC_STg2_UTS_ST ptgDest, CPC_STg2_UTS_ST ptgSrc, C_TgUINT32 uiSrc_Offset, C_TgUINT32 uiSrc_Length )
{
    C_TgUINT32                          uiSize = tgCM_MIN_U32( uiSrc_Length, ptgSrc->m_uiBuffer - uiSrc_Offset );

    TgASSERT( NULL != ptgDest && NULL != ptgSrc );

    if (TgEXPECT_FALSE(!(uiSize > 0 && uiSrc_Offset <= ptgSrc->m_uiBuffer)))
    {
        tgCM_UTS_ST_Clear( ptgDest );
    }
    else
    {
        P_TgCHAR                            pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
        CPC_TgCHAR                          pszSrc = tgCM_UTS_ST_Query_String( ptgSrc );

        if (TgEXPECT_FALSE(tgCM_UTS_ST_Overlap( pszDest, ptgDest->m_uiBuffer, pszSrc, uiSize )))
        {
            C_TgUINT32                          uiOffset = (TgUINT32)(pszSrc - pszDest) + uiSrc_Offset;
            C_TgUINT32                          nuiLeft = tgCM_UTS_ST_Size( ptgDest );

            tgCM_UTS_SF_Erase( ptgDest, uiOffset + uiSize, nuiLeft );
            tgCM_UTS_SF_Erase( ptgDest, 0, uiOffset );
        }
        else
        {
            C_TgUINT32                          uiNew_Reserve = uiSize + 1;

            if (uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
            {
                if (ptgDest->m_uiReserve > ETgSTRING_STATIC_BUFFER_SIZE)
                {
                    TgFREE_POOL( pszDest );
                    ptgDest->m_uiReserve = ETgSTRING_STATIC_BUFFER_SIZE;
                    pszDest = ptgDest->m_unData.m_aBuffer;
                };
            }
            else
            {
                pszDest = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

                if (TgEXPECT_FALSE(0 == pszDest))
                {
                    TgASSERT_MSGF( uiSize > 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Assign") );
                    tgCM_UTS_ST_Clear( ptgDest );
                    return;
                };

                tgCM_UTS_ST_Clear( ptgDest );
                ptgDest->m_unData.m_pszDest = pszDest;
                ptgDest->m_uiReserve = uiNew_Reserve;
            };

            memcpy( pszDest, pszSrc, uiSize * ETgBYTE_PER_CHAR );
            tgCM_UTS_ST_Null_Term( ptgDest, uiSize );
        };
    };
}


TgVOID tgCM_UTS_ST_CH_Append( PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiCount, C_TgCHAR uiChar )
{
    if (TgEXPECT_FALSE(!(0 != uiCount && TgT('\0') != uiChar)))
    {
    }
    else
    {
        C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer + uiCount;
        P_TgCHAR                            pszDest;
    #if TgS_WIDE_CHAR
        TgUINT32                            uiIndex;
    #endif

        tgCM_UTS_ST_Reserve( ptgDest, uiNew_Size );

        TgVERIFY(0 != (pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest )));

#if TgS_WIDE_CHAR
        for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
        {
            pszDest[ptgDest->m_uiBuffer + uiIndex] = uiChar;
        };
#else
        memset( pszDest + ptgDest->m_uiBuffer, uiChar, uiCount );
#endif

        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    };
}


TgVOID tgCM_UTS_ST_SF_Append(
    PC_STg2_UTS_ST ptgDest, CPC_STg2_UTS_ST ptgSrc, C_TgUINT32 uiSrc_Offset, C_TgUINT32 uiSrc_Length )
{
    C_TgUINT32                          uiSize = tgCM_MIN_U32( uiSrc_Length, ptgSrc->m_uiBuffer - uiSrc_Offset );
    C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer + uiSize;
    P_TgCHAR                            pszDest;

    if (TgEXPECT_FALSE(!(uiSize > 0 && uiSrc_Offset <= ptgSrc->m_uiBuffer)))
    {
    }
    else if (ptgDest->m_uiReserve - ptgDest->m_uiBuffer > uiSize )
    {
        TgVERIFY(0 != (pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest )));
        memcpy( pszDest + ptgDest->m_uiBuffer, tgCM_UTS_ST_Query_String( ptgSrc ) + uiSrc_Offset, uiSize * ETgBYTE_PER_CHAR );
        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    }
    else
    {
        PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( (uiNew_Size+1) * ETgBYTE_PER_CHAR );

        if (TgEXPECT_FALSE(0 == pszTemp))
        {
            TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Append") );
            return;
        };

        TgVERIFY(0 != (pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest )));

        memcpy( pszTemp, pszDest, ptgDest->m_uiBuffer * ETgBYTE_PER_CHAR );
        memcpy( pszTemp + ptgDest->m_uiBuffer, tgCM_UTS_ST_Query_String( ptgSrc ) + uiSrc_Offset, uiSize * ETgBYTE_PER_CHAR );

        tgCM_UTS_ST_Clear( ptgDest );
        ptgDest->m_unData.m_pszDest = pszTemp;
        ptgDest->m_uiReserve = uiNew_Size + 1;
        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    };
}


TgVOID tgCM_UTS_ST_CH_Insert( PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiIdx, C_TgUINT32 uiCount, C_TgCHAR uiChar )
{
    C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer + uiCount;
    C_TgUINT32                          uiNew_Reserve = tgCM_MAX_U32( ptgDest->m_uiReserve, uiNew_Size + 1 );
    P_TgCHAR                            pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
#if TgS_WIDE_CHAR
    TgUINT32                            uiIndex;
#endif

    if (TgEXPECT_FALSE(!(uiCount > 0 && uiIdx <= ptgDest->m_uiBuffer)))
    {
    }
    else if (TgEXPECT_FALSE(TgT('\0') == uiChar))
    {
        tgCM_UTS_SF_Erase( ptgDest, uiIdx, ptgDest->m_uiBuffer );
    }
    else if (uiNew_Reserve == ptgDest->m_uiReserve || uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
    {
        pszDest += uiIdx;

        memmove( pszDest + uiCount, pszDest, (ptgDest->m_uiBuffer - uiIdx) * ETgBYTE_PER_CHAR );

    #if TgS_WIDE_CHAR
        for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
        {
            pszDest[uiIndex] = uiChar;
        };
    #else
        memset( pszDest, uiChar, uiCount );
    #endif

        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    }
    else
    {
        PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

        if (TgEXPECT_FALSE(0 == pszTemp))
        {
            TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_CH_Insert") );
            return;
        };

        memcpy( pszTemp, pszDest, uiIdx * ETgBYTE_PER_CHAR );

    #if TgS_WIDE_CHAR
        for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
        {
            pszTemp[uiIdx + uiIndex] = uiChar;
        };
    #else
        memset( pszTemp + uiIdx, uiChar, uiCount );
    #endif

        memcpy( pszTemp + uiIdx + uiCount, pszDest + uiIdx, (ptgDest->m_uiBuffer-uiIdx) * ETgBYTE_PER_CHAR );

        tgCM_UTS_ST_Clear( ptgDest );
        ptgDest->m_unData.m_pszDest = pszTemp;
        ptgDest->m_uiReserve = uiNew_Reserve;
        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    };
}


TgVOID tgCM_UTS_ST_SF_Insert(
    PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiIdx, CPC_STg2_UTS_ST ptgSrc, C_TgUINT32 uiSrc_Offset, C_TgUINT32 uiSrc_Length )
{
    C_TgUINT32                          uiSize = tgCM_MIN_U32( uiSrc_Length, ptgSrc->m_uiBuffer - uiSrc_Offset );
    C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer + uiSize;
    C_TgUINT32                          uiNew_Reserve = tgCM_MAX_U32( ptgDest->m_uiReserve, uiNew_Size + 1 );
    PC_TgCHAR                           pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
    CP_TgCHAR                           pszSrc = tgCM_UTS_ST_Query_String( ptgSrc ) + uiSrc_Offset;

    if (TgEXPECT_FALSE(!(uiSize > 0 && uiSrc_Offset <= ptgSrc->m_uiBuffer && uiIdx <= ptgDest->m_uiBuffer)))
    {
    }
    else if (uiNew_Reserve == ptgDest->m_uiReserve || uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
    {
        if (TgEXPECT_FALSE(tgCM_UTS_ST_Overlap( pszDest+ uiIdx, ptgDest->m_uiBuffer - uiIdx, pszSrc, uiSize )))
        {
            PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiSize * ETgBYTE_PER_CHAR );

            if (TgEXPECT_FALSE(0 == pszTemp))
            {
                TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Insert") );
                return;
            };

            memcpy( pszTemp, pszSrc, uiSize * ETgBYTE_PER_CHAR );

            memmove( pszDest + uiIdx + uiSize, pszDest+ uiIdx, (ptgDest->m_uiBuffer - uiIdx) * ETgBYTE_PER_CHAR );
            memcpy( pszDest+ uiIdx, pszTemp, uiSize * ETgBYTE_PER_CHAR );
            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );

            TgFREE_POOL( pszTemp );
        }
        else
        {
            memmove( pszDest+ uiIdx + uiSize, pszDest+ uiIdx, (ptgDest->m_uiBuffer - uiIdx) * ETgBYTE_PER_CHAR );
            memcpy( pszDest+ uiIdx, pszSrc, uiSize * ETgBYTE_PER_CHAR );
            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
        };
    }
    else
    {
        PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

        if (TgEXPECT_FALSE(0 == pszTemp))
        {
            TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Insert") );
            return;
        };

        memcpy( pszTemp, pszDest, uiIdx * ETgBYTE_PER_CHAR );
        memcpy( pszTemp + uiIdx, pszSrc, uiSize * ETgBYTE_PER_CHAR );
        memcpy( pszTemp + uiIdx + uiSize, pszDest + uiIdx, (ptgDest->m_uiBuffer - uiIdx) * ETgBYTE_PER_CHAR );

        tgCM_UTS_ST_Clear( ptgDest );
        ptgDest->m_unData.m_pszDest = pszTemp;
        ptgDest->m_uiReserve = uiNew_Reserve;
        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    };
}


TgVOID tgCM_UTS_ST_CH_Replace(
    PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiStart, C_TgUINT32 uiEnd, C_TgUINT32 uiCount, C_TgCHAR uiChar )
{
    if (TgEXPECT_FALSE(!(uiStart <= ptgDest->m_uiBuffer && uiEnd <= ptgDest->m_uiBuffer)))
    {
    }
    else if (TgEXPECT_FALSE(0 == uiCount))
    {
        tgCM_UTS_SF_Erase( ptgDest, uiStart, uiEnd-uiStart );
    }
    else if (TgEXPECT_FALSE(TgT('\0') == uiChar))
    {
        tgCM_UTS_SF_Erase( ptgDest, uiStart, ~0u );
    }
    else
    {
        C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer - (uiEnd - uiStart) + uiCount;
        C_TgUINT32                          uiNew_Reserve = tgCM_MAX_U32( ptgDest->m_uiReserve, uiNew_Size + 1 );
        P_TgCHAR                            pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
#if TgS_WIDE_CHAR
        TgUINT32                            uiIndex;
#endif

        if (uiNew_Reserve == ptgDest->m_uiReserve || uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
        {
            memmove( pszDest + uiStart + uiCount, pszDest + uiEnd, (ptgDest->m_uiBuffer - uiEnd) * ETgBYTE_PER_CHAR );

        #if TgS_WIDE_CHAR
            for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
            {
                pszDest[uiStart + uiIndex] = uiChar;
            };
        #else
            memset( pszDest + uiStart, uiChar, uiCount );
        #endif

            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
        }
        else
        {
            PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

            if (TgEXPECT_FALSE(0 == pszTemp))
            {
                TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Insert") );
                return;
            };

            memcpy( pszTemp, pszDest, uiStart * ETgBYTE_PER_CHAR );

        #if TgS_WIDE_CHAR
            for (uiIndex = 0; uiIndex < uiCount; ++uiIndex)
            {
                pszTemp[uiStart + uiIndex] = uiChar;
            };
        #else
            memset( pszTemp + uiStart, uiChar, uiCount );
        #endif

            memcpy( pszTemp + uiStart + uiCount, pszDest + uiEnd, (ptgDest->m_uiBuffer - uiEnd) * ETgBYTE_PER_CHAR );

            tgCM_UTS_ST_Clear( ptgDest );
            ptgDest->m_unData.m_pszDest = pszTemp;
            ptgDest->m_uiReserve = uiNew_Reserve;
            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
        };
    };
}


TgVOID tgCM_UTS_ST_SF_Replace(
    PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiDest_Start, C_TgUINT32 uiDest_End, CPC_STg2_UTS_ST ptgSrc,
    C_TgUINT32 uiSrc_Offset, C_TgUINT32 uiSrc_Length )
{
    C_TgUINT32                          uiSrc_Size = tgCM_MIN_U32( uiSrc_Length, ptgSrc->m_uiBuffer - uiSrc_Offset );
    C_TgUINT32                          uiDest_Size = uiDest_End - uiDest_Start;
    C_TgUINT32                          uiNew_Size = ptgDest->m_uiBuffer - uiDest_Size + uiSrc_Size;
    C_TgUINT32                          uiNew_Reserve = tgCM_MAX_U32( ptgDest->m_uiReserve, uiNew_Size + 1 );
    PC_TgCHAR                           pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );
    CP_TgCHAR                           pszSrc = tgCM_UTS_ST_Query_String( ptgSrc ) + uiSrc_Offset;

    if (TgEXPECT_FALSE(!(
        uiSrc_Offset <= ptgSrc->m_uiBuffer && uiDest_Start <= ptgDest->m_uiBuffer && uiDest_End <= ptgDest->m_uiBuffer)))
    {
    }
    else if (TgEXPECT_FALSE(!(uiSrc_Size > 0)))
    {
        tgCM_UTS_SF_Erase( ptgDest, uiDest_Start, uiDest_Size );
    }
    else if (uiNew_Reserve == ptgDest->m_uiReserve || uiNew_Reserve <= ETgSTRING_STATIC_BUFFER_SIZE)
    {
        PC_TgCHAR                           pszDest_Start = pszDest + uiDest_Start;
        PC_TgCHAR                           pszDest_End = pszDest + uiDest_End;

        if (TgEXPECT_FALSE(tgCM_UTS_ST_Overlap( pszDest, ptgDest->m_uiBuffer - uiDest_Start, pszSrc, uiSrc_Size )))
        {
            PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiSrc_Size * ETgBYTE_PER_CHAR );

            if (TgEXPECT_FALSE(0 == pszTemp))
            {
                TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Replace") );
                return;
            };

            memcpy( pszTemp, pszSrc, uiSrc_Size * ETgBYTE_PER_CHAR );

            memmove( pszDest_Start + uiSrc_Size, pszDest_End, (ptgDest->m_uiBuffer - uiDest_End) * ETgBYTE_PER_CHAR );
            memcpy( pszDest_Start, pszTemp, uiSrc_Size * ETgBYTE_PER_CHAR );
            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );

            TgFREE_POOL( pszTemp );
        }
        else
        {
            memmove( pszDest_Start + uiSrc_Size, pszDest_End, (ptgDest->m_uiBuffer - uiDest_End) * ETgBYTE_PER_CHAR );
            memcpy( pszDest_Start, pszSrc, uiSrc_Size * ETgBYTE_PER_CHAR );
            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
        };
    }
    else
    {
        PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( uiNew_Reserve * ETgBYTE_PER_CHAR );

        if (TgEXPECT_FALSE(0 == pszTemp))
        {
            TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_SF_Replace") );
            return;
        };

        memcpy( pszTemp, pszDest, uiDest_Start * ETgBYTE_PER_CHAR );
        memcpy( pszTemp + uiDest_Start, pszSrc, uiSrc_Size * ETgBYTE_PER_CHAR );
        memcpy( pszTemp + uiDest_Start + uiSrc_Size, pszDest + uiDest_End, (ptgDest->m_uiBuffer - uiDest_End) * ETgBYTE_PER_CHAR );

        tgCM_UTS_ST_Clear( ptgDest );
        ptgDest->m_unData.m_pszDest = pszTemp;
        ptgDest->m_uiReserve = uiNew_Reserve;
        tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
    };
}


/* erase elements [uiOffset, uiOffset + uiLength) */
TgVOID tgCM_UTS_SF_Erase( PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiOffset, C_TgUINT32 uiLength )
{    
    C_TgUINT32                          uiSize = tgCM_MIN_U32( uiLength, ptgDest->m_uiBuffer - uiOffset );
    PC_TgCHAR                           pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest ) + uiOffset;

    if (TgEXPECT_FALSE(!(uiOffset <= ptgDest->m_uiBuffer && uiSize > 0)))
    {
    }
    else
    {
        if (ptgDest->m_uiBuffer > uiOffset + uiSize)
        {
            memmove( pszDest, pszDest + uiSize, (ptgDest->m_uiBuffer - uiSize - uiOffset) * ETgBYTE_PER_CHAR );
        };

        tgCM_UTS_ST_Null_Term( ptgDest, ptgDest->m_uiBuffer - uiSize );
    };
}


TgVOID tgCM_UTS_ST_Resize( PC_STg2_UTS_ST ptgDest, C_TgUINT32 uiNew_Size, C_TgCHAR uiChar )
{
    if (TgEXPECT_FALSE(uiNew_Size > ptgDest->m_uiBuffer && TgT('\0') != uiChar))
    {
        tgCM_UTS_ST_CH_Append( ptgDest, uiNew_Size - ptgDest->m_uiBuffer, uiChar );
    }
    else
    {
        TgUINT32                            uiIndex = ptgDest->m_uiBuffer;
        P_TgCHAR                            pszDest;

        if (uiNew_Size + 1 < ETgSTRING_STATIC_BUFFER_SIZE)
        {
            if (ptgDest->m_uiReserve > ETgSTRING_STATIC_BUFFER_SIZE)
            {
                pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );

                memcpy( ptgDest->m_unData.m_aBuffer, pszDest, tgCM_MIN_U32( uiNew_Size, ptgDest->m_uiBuffer ) * ETgBYTE_PER_CHAR );
                TgFREE_POOL( pszDest );
                ptgDest->m_uiReserve = ETgSTRING_STATIC_BUFFER_SIZE;
            };

            pszDest = ptgDest->m_unData.m_aBuffer;
        }
        else
        {
            PCU_TgCHAR                          pszTemp = (P_TgCHAR)TgMALLOC_POOL( (uiNew_Size + 1) * ETgBYTE_PER_CHAR );

            if (TgEXPECT_FALSE(0 == pszTemp))
            {
                TgASSERT_MSGF( 0, TgT("%-16.16s(%-32.32s): Out of Memory.\n"), TgT("Common"), TgT("CM_UTS_ST_Resize") );
                return;
            };

            pszDest = tgCM_UTS_ST_Get_Buffer( ptgDest );

            if (TgEXPECT_TRUE(ptgDest->m_uiBuffer > 0))
            {
                memcpy( pszTemp, pszDest, tgCM_MIN_U32( uiNew_Size, ptgDest->m_uiBuffer ) * ETgBYTE_PER_CHAR );
            };

            tgCM_UTS_ST_Clear( ptgDest );
            ptgDest->m_unData.m_pszDest = pszTemp;
            ptgDest->m_uiReserve = uiNew_Size + 1;

            pszDest = pszTemp;
        };

        if (TgT('\0') != uiChar && uiNew_Size > uiIndex)
        {
        #if TgS_WIDE_CHAR
            for (; uiIndex < uiNew_Size; ++uiIndex)
            {
                pszDest[uiIndex] = uiChar;
            };
        #else
            memset( pszDest + uiIndex, uiChar, uiNew_Size - uiIndex );
        #endif

            tgCM_UTS_ST_Null_Term( ptgDest, uiNew_Size );
        }
        else
        {
            tgCM_UTS_ST_Null_Term( ptgDest, tgCM_MIN_U32( uiIndex, uiNew_Size ) );
        };
    };
}


// look for [pszRight, pszRight + uiRLength) beginning at or after uiOffset
TgUINT32 tgCM_UTS_SO_SF_Find_String(
    CPC_STg2_UTS_ST ptgLeft, C_TgUINT32 uiLOffset, CPC_STg2_UTS_ST ptgRight, C_TgUINT32 uiROffset, C_TgUINT32 uiRLength )
{
    C_TgUINT32                          uiRSize = tgCM_MIN_U32( uiRLength, ptgRight->m_uiBuffer - uiROffset );
    C_TgUINT32                          uiLSize = ptgLeft->m_uiBuffer - uiLOffset;

    if (TgEXPECT_FALSE(
        !(uiLSize > 0 && uiRSize > 0 && uiLOffset + uiRSize <= ptgLeft->m_uiBuffer && uiROffset <= ptgRight->m_uiBuffer )))
    {
        return (~0u);
    }
    else
    {
        CPC_TgCHAR                          pszRight = tgCM_UTS_ST_Query_String( ptgRight ) + uiROffset;
        CPC_TgCHAR                          pszLeft = tgCM_UTS_ST_Query_String( ptgLeft );
        CPC_TgCHAR                          pszLast = pszLeft + (ptgLeft->m_uiBuffer-1) - (uiRSize-1);
        CP_TgCHAR                           pszCurrent = pszLeft + uiLOffset;

        while (1)
        {
            for (;*pszCurrent != *pszRight && pszCurrent <= pszLast; ++pszCurrent);

            if (TgEXPECT_FALSE(!(pszCurrent <= pszLast)))
            {
                break;
            };

            if (0 == tgSZ_CompareN( pszCurrent, pszRight, uiRSize ))
            {
                return ((TgUINT32)(pszCurrent - pszLeft)); // found a match
            };

            ++pszCurrent;
        };

        return (~0u);
    };
}


// look for [pszRight, pszRight + uiCount) beginning at or after uiOffset
TgUINT32 tgCM_UTS_SO_SF_RFind_String(
    CPC_STg2_UTS_ST ptgLeft, C_TgUINT32 uiLOffset, CPC_STg2_UTS_ST ptgRight, C_TgUINT32 uiROffset, C_TgUINT32 uiRLength )
{
    C_TgUINT32                          uiSize = tgCM_MIN_U32( uiRLength, ptgRight->m_uiBuffer - uiROffset );

    if (TgEXPECT_FALSE(!(uiSize > 0 && uiROffset <= ptgRight->m_uiBuffer && uiLOffset + uiSize <= ptgLeft->m_uiBuffer )))
    {
        return (~0u);
    }
    else
    {
        CPC_TgCHAR                          pszRight = tgCM_UTS_ST_Query_String( ptgRight ) + uiROffset;
        CPC_TgCHAR                          pszLeft = tgCM_UTS_ST_Query_String( ptgLeft );
        CP_TgCHAR                           pszCurrent = pszLeft - uiLOffset + (ptgLeft->m_uiBuffer-1) - (uiSize-1);

        while (1)
        {
            for (;*pszCurrent != *pszRight && pszCurrent >= pszLeft; --pszCurrent);

            if (TgEXPECT_FALSE(!(pszCurrent >= pszLeft)))
            {
                break;
            };

            if (0 == tgSZ_CompareN( pszCurrent, pszRight, uiSize ))
            {
                return ((TgUINT32)(pszCurrent - pszLeft)); // found a match
            };

            --pszCurrent;
        };

        return (~0u);
    };
}




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Internal Interface
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

/* determine current pointer to buffer for non mutable string */
TgFORCEINLINE P_TgCHAR tgCM_UTS_ST_Get_Buffer( PCU_STg2_UTS_ST ptgDest )
{
    return (ETgSTRING_STATIC_BUFFER_SIZE < ptgDest->m_uiReserve ? ptgDest->m_unData.m_pszDest : ptgDest->m_unData.m_aBuffer);
}


/* set new length and null terminator */
TgFORCEINLINE TgVOID tgCM_UTS_ST_Null_Term( PCU_STg2_UTS_ST ptgDest, C_TgUINT32 uiNewSize )
{
    tgCM_UTS_ST_Get_Buffer(ptgDest)[ptgDest->m_uiBuffer = uiNewSize] = TgT('\0');
}


TgFORCEINLINE TgBOOL tgCM_UTS_ST_Overlap( CPC_TgVOID pData0, C_TgSIZE uiRng0, CPC_TgVOID pData1, C_TgSIZE uiRng1 )
{
    return (!(
        ((TgUINTPTR)pData0 >= (TgUINTPTR)pData1 + uiRng1*ETgBYTE_PER_CHAR) ||
        ((TgUINTPTR)pData0 + uiRng0*ETgBYTE_PER_CHAR <  (TgUINTPTR)pData1)
    ));
}