#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/string/strlen.c,v 1.7 2009/01/26 07:31:28 delphij Exp $");
#include <limits.h>
#include <sys/types.h>
#include <string.h>
#if LONG_BIT == 32
static const unsigned long mask01 = 0x01010101;
static const unsigned long mask80 = 0x80808080;
#elif LONG_BIT == 64
static const unsigned long mask01 = 0x0101010101010101;
static const unsigned long mask80 = 0x8080808080808080;
#else
#error Unsupported word size
#endif
#define LONGPTR_MASK (sizeof(long) - 1)
/*
* Helper macro to return string length if we caught the zero
* byte.
*/
#define testbyte(x) \
do { \
if (p[x] == '\0') \
return (p - str + x); \
} while (0)
size_t
strlen(const char *str)
{
const char *p;
const unsigned long *lp;
/* Skip the first few bytes until we have an aligned p */
for (p = str; (uintptr_t)p & LONGPTR_MASK; p++)
if (*p == '\0')
return (p - str);
/* Scan the rest of the string using word sized operation */
for (lp = (const unsigned long *)p; ; lp++)
if ((*lp - mask01) & mask80) {
p = (const char *)(lp);
testbyte(0);
testbyte(1);
testbyte(2);
testbyte(3);
#if (LONG_BIT >= 64)
testbyte(4);
testbyte(5);
testbyte(6);
testbyte(7);
#endif
}
/* NOTREACHED */
return (0);
}
http://www.opensource.apple.com/source/Libc/Libc-997.1.1/string/FreeBSD/strlen.c
bsd계열과 sparc 계열에 유사 소스가 있네요.
오래된 테크닉이야. 몇십년 묵음.
근데 요렇게만 하면 다국어 처리 못함.
저건 0x7F 까지 정의된 코드에서나 유효할듯.
조건문 연산량은 줄어서 빠를테고, 루프 확장을 안해서 느림. 즉 0x80이상의 코드에서도 제대로 돌도록 구현하면 내꺼보다 느린 코드.
그렇군요.
제목은 좀 이상하네요. 애플이 구현한건 아닌데... 내가 써놓고도 참ㅋㅋ
옛날 시스템은 파이프라인이 적어서 저런식으로 루프로 짜는게 득이었지.
(*lp - mask01) & mask80) 요 연산이 문젠데 ~*lp 랑 AND 해주지 않으면 0x80 이상의 코드에서 오동작하지.
지금은 캐시빨과 파이프라인빨로 언롤링해주는게 확실히 빨라.
만약 0x7F 까지의 아스키코드만 사용할땐, 내가 짠 코드에서 ~w[n] 이랑 & 하는 부분을 지워주면 훨 빨라짐.
그정도까지 다 생각하고 계신거군요. 대단합니다.
인라인 어셈코드 고쳐놨다~
http://www.opensource.apple.com/source/Libc/Libc-1044.1.2/string/FreeBSD/strlen.c
채신코드봅시다