![viewimage.php?id=3dafdf21f7d335ab67b1d1&no=29bcc427b38177a16fb3dab004c86b6f1a1232ae65b3ad2636808df24674120cacd2bcd6900205cfb9b027fbf4f6e46212846af2dcb0391b601a8ca2ad]()
#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] == 0) return 0;
if (str[1] == 0) return 1;
if (str[2] == 0) return 2;
if (str[3] == 0) return 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 <=
퍄... 이거 카피레프트임니까
사용해도 되는지
사용하는 건 상관없어요
꽤 오래된 논란이었구나