NO

Author Topic: stristr  (Read 15269 times)

JohnF

  • Guest
stristr
« Reply #15 on: September 09, 2005, 08:19:51 am »
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

  • Guest
stristr
« Reply #16 on: September 09, 2005, 02:28:23 pm »
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

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 1974
    • http://www.smorgasbordet.com
stristr
« Reply #17 on: September 09, 2005, 06:55:37 pm »
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

  • Guest
stristr
« Reply #18 on: September 10, 2005, 08:32:55 am »
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

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 1974
    • http://www.smorgasbordet.com
stristr
« Reply #19 on: September 10, 2005, 06:08:57 pm »
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

  • Guest
stristr
« Reply #20 on: September 10, 2005, 08:40:54 pm »
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

  • Guest
stristr
« Reply #21 on: September 10, 2005, 09:11:26 pm »
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.

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 1974
    • http://www.smorgasbordet.com
stristr
« Reply #22 on: September 10, 2005, 11:14:36 pm »
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.

Code: [Select]

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

  • Guest
stristr
« Reply #23 on: September 11, 2005, 01:41:33 pm »
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.

Offline Robert

  • Member
  • *
  • Posts: 187
Re: stristr
« Reply #24 on: July 30, 2008, 10:07:28 am »
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.

Code: [Select]
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


Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 1974
    • http://www.smorgasbordet.com
Re: stristr
« Reply #25 on: September 23, 2008, 07:43:50 pm »
Can the casts be modified so the warnings do not appear?
The quick & dirty solution:
change from:
Code: [Select]
lut_lower = (char)(int)CharLowerA((char *)(unsigned char)i);to:
Code: [Select]
lut_lower = (char)(long long)CharLowerA((char *)(unsigned char)i);
/Pelle