unsigned char   lower_ascii[ 0x100 ];


inline  size_t  has_zero_byte( const size_t n ) // 32bit 전용

{

    const   size_t  finder = (size_t)0x01010101;

    const   size_t  masker = (size_t)0x80808080;

    return ( n - finder ) & ( ~n & masker );

}


inline  size_t  has_some_byte( const unsigned char* s, const unsigned char c )

{

    return  lower_ascii[ s[ 0 ] ] == c || lower_ascii[ s[ 1 ] ] == c ||

            lower_ascii[ s[ 2 ] ] == c || lower_ascii[ s[ 3 ] ] == c;

}


inline  char*   istrstr( const unsigned char* src, const unsigned char* sub )

{

    unsigned char* s = (unsigned char*)src;

    unsigned char* r = (unsigned char*)sub;

    unsigned char* o = s;

    while( *s )

    {

        if( lower_ascii[ *s ] == lower_ascii[ *r ] )

        {

            s++;

            r++;

            if ( !*r ) return (char*)o - 1; 

        }

        else

        {

            s = o++;

            r = (unsigned char*)sub;

        }

    }

    return NULL;

}


#include <string.h>


int     ex_strncmp( const unsigned char* s1, const unsigned char* s2, const size_t length )

{

    for( size_t i = 0; i < length; ++i )

    {

        if( s1[ i ] & 0x80 )

        {

            if ( *(short*)( s1 + i ) != *(short*)( s2 + i ) )

                return *(short*)(s1 + i) - *(short*)(s2 + i) ;

            i++;

        }

        else

        {

            if ( lower_ascii[ s1[ i ] ] != lower_ascii[ s2[ i ] ] )

                return lower_ascii[ s1[ i ] ] - lower_ascii[ s2[ i ] ];

        }

    }

    return 0;

}


char*   ex_strstr( const char* src, const char* sub )

{

    if( !lower_ascii[ 0xFF ] )

    {

        size_t i;

        for( i = 0; i < 'A'; ++i ) lower_ascii[ i ] = (unsigned char)i;

        for( ; i <= 'Z'; ++i ) lower_ascii[ i ] = (unsigned char)i | 0x20;

        for( ; i < 0x100; ++i ) lower_ascii[ i ] = (unsigned char)i;

    }

    if( !( (size_t)src | (size_t)sub ) ) return NULL;


    unsigned char* s = (unsigned char*)src;

    unsigned char* r = (unsigned char*)sub + 1;

    unsigned char  c = lower_ascii[ *(unsigned char*)sub ];

    if( !*r )

    {

        while( !has_zero_byte( *(size_t*)s ) )

        {

            if( has_some_byte( s, c ) )

            {

                while( lower_ascii[ *s++ ] != c );

                return (char*)s - 1;

            }

            else s += 4;

        }

    }

    else

    {

        while( !has_zero_byte( *(size_t*)s ) )

        {

            if( has_some_byte( s, c ) )

            {

                unsigned char* ss = s;

                s += 4;

                while( lower_ascii[ *ss++ ] != c );

                retry:

                for( int i = 0; lower_ascii[ ss[ i ] ] == lower_ascii[ r[ i ] ]; ++i )

                {

                    if( !ss[ i ] ) return NULL;

                    if( !r[ i + 1 ] )

                    {

                        if( !ex_strncmp( ss - 1, (unsigned char*)sub, i + 1 ) )

                            return (char*)ss - 1;

                        else break;

                    }

                }

                do if( lower_ascii[ *ss++ ] == c ) goto retry; while( ss < s );

            }

            else s += 4;

        }

    }

    return istrstr(s, (unsigned char*)sub);

}


#include <intrin.h>

#include <iostream>

#include <fstream>

using namespace std;


int main()

{

    ifstream ifs;

    ifs.open( "c:\input.txt", ios::in | ios::binary );

    ifs.seekg( 0, ifs.end );

    size_t size = ifs.tellg();

    char* src = new char[ size + 1 ];

    src[ size ] = 0;

    ifs.seekg( 0, ifs.beg );

    ifs.read( src, size );

    ifs.close();

    cout << "File Size : " << size << endl;


    __int64 begin, elapsed1, elapsed2;


    begin = __rdtsc();

    char* ptr1 = strstr( src, "검색어" );

    size_t position_strstr          = ptr1 - src;

    if( !ptr1 ) position_strstr     = 0;

    elapsed1 = __rdtsc() - begin;


    begin = __rdtsc();

    char* ptr2 = ex_strstr( src, "검색어" );

    size_t position_strstr_i        = ptr2 - src;

    if( !ptr2 ) position_strstr_i   = 0;

    elapsed2 = __rdtsc() - begin;


    delete[] src;


    cout << position_strstr     << "    " << elapsed1 << endl;

    cout << position_strstr_i   << "    " << elapsed2 << endl;


    getchar();

    return 0;

}