#if defined(__x86_64__) || defined(__ia64__) || defined(_M_AMD64) || defined(_M_IA64) 

    || defined(_WIN64) || defined(__alpha__) || defined(__s390__)
#define _X64_MODE
typedef uint64_t    checker_type;
#else
typedef uint32_t    checker_type;
#endif
 
#define _MAGIC    checker_type(~0ULL/0xff)
 
size_t strlen(const char* str)
{
    if (str[0== 0return 0;
    if (str[1== 0return 1;
    if (str[2== 0return 2;
    if (str[3== 0return 3;
 
    checker_type* trim = 
#ifdef _X64_MODE
                (checker_type *)(((checker_type)str & -8LL) + 8);
#else
                (checker_type *)(((checker_type)str & -4L) + 4);
#endif
 
#define _ZIF(n)  if( (trim[n] - _MAGIC) & ((_MAGIC) << 7) ) {trim += n; break;}
 
    while (true)
    {
    TRYRE:
        _ZIF( 0)_ZIF( 1)_ZIF( 2)_ZIF( 3)
        _ZIF( 4)_ZIF( 5)_ZIF( 6)_ZIF( 7)
        _ZIF( 8)_ZIF( 9)_ZIF(10)_ZIF(11)
        _ZIF(12)_ZIF(13)_ZIF(14)_ZIF(15)
 
        trim += 16;
    }

    if (!(trim[0] & ( 0xffUL << (8 * 0)))) return ((size_t)trim - (size_t)str) + 0;
    if (!(trim[0] & ( 0xffUL << (8 * 1)))) return ((size_t)trim - (size_t)str) + 1;
    if (!(trim[0] & ( 0xffUL << (8 * 2)))) return ((size_t)trim - (size_t)str) + 2;
    if (!(trim[0] & ( 0xffUL << (8 * 3)))) return ((size_t)trim - (size_t)str) + 3;
#ifdef _X64_MODE
    if (!(trim[0] & (0xffULL << (8 * 4)))) return ((size_t)trim - (size_t)str) + 4;
    if (!(trim[0] & (0xffULL << (8 * 5)))) return ((size_t)trim - (size_t)str) + 5;
    if (!(trim[0] & (0xffULL << (8 * 6)))) return ((size_t)trim - (size_t)str) + 6;
    if (!(trim[0] & (0xffULL << (8 * 7)))) return ((size_t)trim - (size_t)str) + 7;
#endif
    trim++goto TRYRE; // Has Ansi Byte가 127 보다큰 숫자를 물어왔다.
}


ANSI가 0xff까지 있지만 127비트보다 큰건 거의 사용을 안한다.

따라서 1~127만 건너 뛰면 된다.

0, 128~255를 검출하는 검색기를 이용해 찾는 방법이다.


이는 컴퓨터 감산 연산시 음수가되면 msb가 변하는 현상을 이용한 것이다.

0x00 - 0x01 => 0xFF ,

0x10000101 - 0x01010101 => 0EFF 0000


wcslen의 경우엔 0x8000(32768)부터 못 쓰게 되는 것이므로, 그리고 여기엔 한글유니코드가 포함되므로, has zero byte사용은 불가피하다.


============통계============

실험 함수

void testlen()

{

#define L1(x) x x x x

#define L2(x) L1(x) L1(x) L1(x) L1(x)

#define L3(x) L2(x) L2(x) L2(x) L2(x)

#define L4(x) L3(x) L3(x) L3(x) L3(x)

#define L5(x) L4(x) L4(x) L4(x) L4(x)

#define L6(x) L5(x) L5(x) L5(x) L5(x)

#define L7(x) L6(x) L6(x) L6(x) L6(x)

    const char testTarget[] =  L6("koromo");

    char* testCopy = new char[sizeof(testTarget)];

    memcpy(testCopy, testTarget, sizeof(testTarget));

 

    Timer<long double> timer;

    timer.start();

    size_t length = strlen(testCopy);

    timer.finish();

 

    std::cout << length << std::endl;

    timer.outms();

}


32bit 모드-------------------------------------------


mcvcpp strlen 내장 ( ((( ptr  + 0x7efefeff ) ^ ~ptr) & 0x81010100) 핵스레이로 가져옴 )

24576
0.0138336904805467ms
24576
0.0138336904805467ms
24576
0.0138336904805467ms
24576
0.0174036751206878ms
24576
0.0191886674407583ms

strlen 구현
24576
0.00490872888019399ms
24576
0.00490872888019399ms
24576
0.00446248080017636ms
24576
0.00758621736029981ms
24576
0.00535497696021163ms

64bit 모드-------------------------------------------


mcvcpp strlen 내장 ( x86 함수를 그냥 사용하는 것같다 )

24576

0.0169574270406702ms

24576

0.0165111789606525ms

24576

0.0187424193607407ms

24576

0.0174036751206878ms

24576

0.0182961712807231ms


strlen 구현
24576
0.00356998464014109ms
24576
0.00178499232007054ms
24576
0.00223124040008818ms
24576
0.00356998464014109ms
24576
0.00356998464014109ms

결론 :
x86
127has_no_ansi > haszerobyte >> 내장

x64
127has_no_ansi >> haszerobyte >>>>> 내장

참고로 ms내장 wcslen함수는 상대할 가치가 없다.

이렇게 추가해도 될 것 같다.
if ((trim[0] - ( _MAGIC)) & ((~trim[0] & (( _MAGIC) << 7))))
{
trim++;
goto TRYRE;
}
 

---------------------------------------------------------------
참고문헌

http://gall.dcinside.com/board/view/?id=programming&no=504522

http://gall.dcinside.com/board/view/?id=programming&no=505067


=> powered by codesafer <=