Fixing 'strlen' Code [Resolved - Now Discussion Stuff]

Started by
19 comments, last by GameDev.net 18 years, 11 months ago
So I've been browsing though some of the older posts in the forums and I cam across this from Magmai Kai Holmlor:
  
  int strlen(const char* cszStr)
  {
	DWORD* p = (DWORD*) cszStr;
	DWORD k,kk;
	
	while(DWORD(p)&3)
		{
		if(*(char*)(p)==0)
			return (char*)(p)-cszStr;
		p = (DWORD*) (((char*)(p)) + 1);
		}
	
	do
		{
		k = *p;
		kk = k + 0x7efefeff;
		k ^= -1;
		k ^= kk;
		p++;
		} while(!(k&0x81010100));
	
	k = *(--p);
	if(!(k&0x000000ff))
		return (char*)(p)-cszStr;
	
	//if(!(k&0x0000ffff)) Thanks Kippesoep! [smile]
        if(!(k&0x0000ff00))
		return (char*)(p)-cszStr+1;
	
	if(!(k&0x00ff0000))
		return (char*)(p)-cszStr+2;
	
	if(!(k&0xff000000))
		return (char*)(p)-cszStr+3;
	
	return (char*)(p)-cszStr;
  }
  


Looked fairly interesting so I gave it a try. Worked good for the most part, except when the string sent in is one character, as seen in this demo program:

int main( int argc, char* argv[] )
{
	char* str = "";
	// Returns 0 (as expected)
	printf("Length of %s: %i\n", str, __strlen__(str) );

	// Returns 2 (not as expected)
	str = "a";
	printf("Length of %s: %i\n", str, __strlen__(str) );

	// Returns 2 (as expected)
	str = "ab";
	printf("Length of %s: %i\n", str, __strlen__(str) );

	// Returns 100 (as expected)
	str = "1111111111__________1111111111__________1111111111__________1111111111__________1111111111__________";
	printf("Length of %s: %i\n", str, __strlen__(str) );

        // Returns 3 (as expected)
	char temp[256] = { '1', '2', '3', '\0' };
	printf("Length of %s: %i\n", temp, __strlen__(temp) );
}



So does anyone have any ideas to how it can work for a character of length 1? In particular, is this algorithm 'acceptable' to find the length of a string? This is just for knowledge and understanding, so please no "use strlen()" or "use std::string.size()" [wink]. Thanks! [Edited by - Drew_Benton on April 26, 2005 2:34:33 AM]
Advertisement
The line
if(!(k&0x0000ffff))

should be
if(!(k&0x0000ff00))

Kippesoep
Is that really that much more efficient than just doing:

int strlen(char* cszStr){ int ctr=0; while (*cszStr++)   ++ctr; return ctr;}


Especially considering that most calls to strlen aren't really the cause for a slowdown in a game :P. You could even do something like this if you're concerned about comparing chars vs. integers:

int strlen(char* cszStr){ int ctr=0; unsigned int *ptrStr = (unsigned int*)cszStr; do {  if (!(ptrStr&0x000000ff))   break;  ++ctr;  if (!(ptrStr&0x0000ff00))   break;  ++ctr;  if (!(ptrStr&0x00ff0000))   break;  ++ctr;  if (!(ptrStr&0xff000000))   break;  ++ctr; } return ctr;}


I don't really think that'll be any more efficient though :P.
Quote:Original post by Kippesoep
The line
if(!(k&0x0000ffff))

should be
if(!(k&0x0000ff00))


[smile] Thanks! That was it. I hope Magmai sees this...

Oh, Ready4Dis, I was only interested in this method because I've never seen it before [wink]. I have yet to play around with other techniques that are the most efficient or fast. I just wanted to see if this does indeed work, as it does thanks to the fix Kippesoep found.

I will be doing further 'research' just for fun. I'll be glad to post my findings on how good this is, but so far, it looks excelent! it's definitly not O( n ) as is when you go though looking for a NULL [grin].
Sheeeshhh, optimized strlen!!! Use Pascal type strings then, where you store lenght in 1st n bytes...
______________________________Madman
unsigned int strlen(const char* str) {    const char *s;    for (s = str; *s; ++s)       ;    return (s - str); }


Works well for me.
Optimizing strlen is just silly. Needing to go through the entire string just to see how long it is will always be slow no matter how clever you are. Real string implementations store the string's length or a pointer to the end of the string.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
Quote:Original post by _Madman_
Sheeeshhh, optimized strlen!!! Use Pascal type strings then, where you store lenght in 1st n bytes...


I have a shortstring template for that.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Since changing strings can be expensive (like appending when you don't have a string length ;) )why not just do something like struct { int len, char* str } like other people have said.
Thats a really nifty method magmai.

Any chance you could tell us how it actually works?

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.

This topic is closed to new replies.

Advertisement