News:

Download Pelles C here: http://www.smorgasbordet.com/pellesc/

Main Menu

stristr

Started by JohnF, September 07, 2005, 08:17:28 AM

Previous topic - Next topic

JohnF

Quote from: "Mikehg"Hi John and Pelle,

I had wondered about the local stuff, but couldn't really find any info that satisfied my questions :)  Since BCX trys to cater to many different compilers, I try to write the runtimes that work across all of them with similar performance.  Just for comparison, I had setup a small benchmark. Using the code above returned about .15 secs. Using tolower() had no significant diffference with PellesC, but with LCC-Win32, VC++ and others returned with greater than 1 sec. Makes you wonder what these other compilers have under the hood :)  Another good example was a replace function I tested once that uses strstr. One particular test only took millisecs with PellesC, and over 30 secs. with others!

Thanks,
Mike Henning

To be safe you could use that listing I posted above. With a test I got 78ms for PellesC and 110ms for VC6 and lcc-win32.

Make sure you don't get a name conflict with already defied names.

John

Gerome

Hello,

VC++ like LCC Win32 don't produce 'by default' really optimized ASM code, but i bet if you put some #pragma optimize(1) under LCC Win32 the result would be better AND if you link your program with -nolibc it'll be better :)

Quote from: "Mikehg"Hi John and Pelle,

I had wondered about the local stuff, but couldn't really find any info that satisfied my questions :)  Since BCX trys to cater to many different compilers, I try to write the runtimes that work across all of them with similar performance.  Just for comparison, I had setup a small benchmark. Using the code above returned about .15 secs. Using tolower() had no significant diffference with PellesC, but with LCC-Win32, VC++ and others returned with greater than 1 sec. Makes you wonder what these other compilers have under the hood :)  Another good example was a replace function I tested once that uses strstr. One particular test only took millisecs with PellesC, and over 30 secs. with others!

Thanks,
Mike Henning

Pelle

Quote from: "Mikehg"Using tolower() had no significant diffference with PellesC, but with LCC-Win32, VC++ and others returned with greater than 1 sec. Makes you wonder what these other compilers have under the hood :)
The default for Pelles C is to define a macro for tolower(), which will fetch the character from a lookup table (that can change with the locale) - just inline code, no function call.

It looks like Microsoft, and probably LCC-Win32 too, is using a true function call. I think Microsoft is more ambitious about supporting things like Japanese which might explain why they need to call a function (too much code to inline).

Pelle
/Pelle

JohnF

Quote from: "Pelle"The default for Pelles C is to define a macro for tolower(), which will fetch the character from a lookup table (that can change with the locale) - just inline code, no function call.

It looks like Microsoft, and probably LCC-Win32 too, is using a true function call. I think Microsoft is more ambitious about supporting things like Japanese which might explain why they need to call a function (too much code to inline).

Pelle

A bit of a mystery - so how would the GetKeyboardState API work for Japanese - presumably Japanese has more than 256 keyboard characters.

=============
BOOL GetKeyboardState(PBYTE lpKeyState);

lpKeyState - Pointer to the 256-byte array that receives the status data for each virtual key.
=============

John

Pelle

Quote from: "JohnF"A bit of a mystery - so how would the GetKeyboardState API work for Japanese - presumably Japanese has more than 256 keyboard characters.

=============
BOOL GetKeyboardState(PBYTE lpKeyState);

lpKeyState - Pointer to the 256-byte array that receives the status data for each virtual key.
=============

John
I don't know enough about Japanese (Windows) to answer this. I was making a guess, and might be completely wrong.

Microsoft is usually good at optimizing for speed in the C runtime, so if full optimization for speed still results in a function call, something complicated must be going on...

Pelle
/Pelle

JohnF

Quote
Microsoft is usually good at optimizing for speed in the C runtime, so if full optimization for speed still results in a function call, something complicated must be going on...

Yes they are usually good so you are probably right.

John

Mikehg

Gerome:
All of the tests were ran with the compilers optimized for speed.

John:

The code you posted seems to be the best choice. Borlands free C++5.5 doesn't seem to support the non-standard strnicmp though :(

Pelle:

After looking through the header files I kind of figured the table was the difference here. Any tips on creating a table that I could supply myself? :)


Thanks guys,

Mike H.

Pelle

Quote from: "Mikehg"After looking through the header files I kind of figured the table was the difference here. Any tips on creating a table that I could supply myself? :)

Not sure it helps, but here is one (quick & dirty) way of doing it. The only point in using this would be to support international characters - otherwise some variation of your original code should be enough.


int __cdecl _tolower(int c)
{
   /* static to keep values between calls */
   static char lut_lower[256];

   /* table not initialized yet? */
   if (lut_lower['a'] == 0)
   {
       int i;

       /* walk through all supported character values (0 - 255) */
       for (i = 0; i < 256; i++)
       {
           /* use CharLower() for international support(?) */
           lut_lower[i] = (char)(int)CharLowerA((char *)(unsigned char)i);
       }
   }

   /* use the table */
   return lut_lower[(unsigned char)c];
}


Pelle
/Pelle

Mikehg

Quote
Not sure it helps, but here is one (quick & dirty) way of doing it. The only point in using this would be to support international characters - otherwise some variation of your original code should be enough.

Pelle

Hi Pelle,

For some reason I was thinking it was going to be a lot more complicated :)  This will help a lot.

Thanks,
Mike H.

Robert

Quote from: Pelle on September 10, 2005, 11:14:36 PM
Quote from: MikehgAfter looking through the header files I kind of figured the table was the difference here. Any tips on creating a table that I could supply myself? :)

Not sure it helps, but here is one (quick & dirty) way of doing it. The only point in using this would be to support international characters - otherwise some variation of your original code should be enough.


int __cdecl _tolower(int c)
{
   /* static to keep values between calls */
   static char lut_lower[256];

   /* table not initialized yet? */
   if (lut_lower['a'] == 0)
   {
       int i;

       /* walk through all supported character values (0 - 255) */
       for (i = 0; i < 256; i++)
       {
           /* use CharLower() for international support(?) */
           lut_lower[i] = (char)(int)CharLowerA((char *)(unsigned char)i);
       }
   }

   /* use the table */
   return lut_lower[(unsigned char)c];
}


Pelle

Using Pelle's C 5.01 x64, the line

lut_lower = (char)(int)CharLowerA((char *)(unsigned char)i);

generates these warnings

snip.c(175): warning #2006: [ISO] Conversion from 'char *' to 'int' is compiler dependent.
snip.c(175): warning #2052: Conversion from 'char *' to 'int' is undefined.

Can the casts be modified so the warnings do not appear?

Thank you

Robert Wishlaw


Pelle

Quote from: Robert on July 30, 2008, 10:07:28 AM
Can the casts be modified so the warnings do not appear?
The quick & dirty solution:
change from:
lut_lower = (char)(int)CharLowerA((char *)(unsigned char)i);
to:
lut_lower = (char)(long long)CharLowerA((char *)(unsigned char)i);
/Pelle