Pelles C forum

Pelles C => Feature requests => Topic started by: JohnF on September 07, 2005, 08:17:28 AM

Title: stristr
Post by: JohnF on September 07, 2005, 08:17:28 AM
I don't know if this has been asked before but, it would be handy to have 'stristr' as pat of the PellesC standard library. I don't know why the standards committee has not included it.

John
Title: stristr
Post by: frankie on September 07, 2005, 10:14:29 AM
I agree John, I haven't asked yet, but I put a remark in my webserver sample code.
It would also be nice to have the fcloseall() M$ historical function.
Title: Re: stristr
Post by: Pelle on September 07, 2005, 05:01:07 PM
Quote from: "JohnF"
I don't know if this has been asked before but, it would be handy to have 'stristr' as pat of the PellesC standard library.

Yes, probably useful. Since it's not part of Standard C and, as far as I can tell, not part of Posix or the Microsoft runtime, it would be a very private extension - only useful in Pelles C. Not sure how good this is...

If portability is not a big issue, there is always the Windows function StrStrI() - in shlwapi.h.

Pelle
Title: stristr
Post by: Pelle on September 07, 2005, 05:02:25 PM
Quote from: "frankie"
It would also be nice to have the fcloseall() M$ historical function.

Right - I have missed this case. Will be added...

Pelle
Title: stristr
Post by: frankie on September 07, 2005, 05:32:50 PM
Quote from: "Pelle"
Quote from: "frankie"
It would also be nice to have the fcloseall() M$ historical function.

Right - I have missed this case. Will be added...

Pelle


Thanks Pelle, could you also revise the addin.h becouse the constants for the AddIn_FindSourceText (FR_DOWN and FR_MATCHCASE) are not defined.
About the stristr function even though it is not part of the standard could be found it in many compilers. Anyway it is not a big issue unless when porting code.
Title: Re: stristr
Post by: JohnF on September 07, 2005, 05:51:58 PM
Quote from: "Pelle"
Quote from: "JohnF"
I don't know if this has been asked before but, it would be handy to have 'stristr' as pat of the PellesC standard library.

Yes, probably useful. Since it's not part of Standard C and, as far as I can tell, not part of Posix or the Microsoft runtime, it would be a very private extension - only useful in Pelles C. Not sure how good this is...

Pelle


Doesn't GCC use it? Anyway, it is useful! :)

This seems to be a common implimentation of it.

Code: [Select]

char * _stristr(const char * szSrc, const char * cszSrch)
{
const int nLength = strlen(cszSrch);
while(*szSrc)
{
if(!_strnicmp(szSrc, cszSrch, nLength))
break;
szSrc++;
}

if(!(*szSrc))
return NULL;
else
return (char*)szSrc;
}


John
Title: stristr
Post by: Pelle on September 07, 2005, 06:59:18 PM
Quote from: "frankie"
Thanks Pelle, could you also revise the addin.h becouse the constants for the AddIn_FindSourceText (FR_DOWN and FR_MATCHCASE) are not defined.

They are defined in commdlg.h - but the help file should say so.

Quote from: "frankie"

About the stristr function even though it is not part of the standard could be found it in many compilers. Anyway it is not a big issue unless when porting code.

Always as an extension, AFAIK. I guess this is part of the problem - if I start adding various compiler extensions, the C library will quickly become very large and complex.

Pelle
Title: Re: stristr
Post by: Pelle on September 07, 2005, 07:11:43 PM
Quote from: "JohnF"
Doesn't GCC use it? Anyway, it is useful! :)

I think they have strcasestr - as a GNU extension.

Quote from: "JohnF"

This seems to be a common implimentation of it.

OK, thanks.

One problem is that there are still some standard C functions missing (complex math). There are probably more Posix functions to add. Maybe something Microsoft specific too. Adding extension on top of that - I just don't know. I don't want the C runtime to grow *too* big...

Pelle
Title: Re: stristr
Post by: JohnF on September 07, 2005, 09:22:54 PM
Quote from: "Pelle"
Quote from: "JohnF"
Doesn't GCC use it? Anyway, it is useful! :)

I think they have strcasestr - as a GNU extension.

Quote from: "JohnF"

This seems to be a common implimentation of it.

OK, thanks.

One problem is that there are still some standard C functions missing (complex math). There are probably more Posix functions to add. Maybe something Microsoft specific too. Adding extension on top of that - I just don't know. I don't want the C runtime to grow *too* big...

Pelle


Ok, you must do what you think is best.

John
Title: stristr
Post by: Pelle on September 07, 2005, 09:58:14 PM
I have been thinking... maybe more consistent to add the following functions after all: _stristr, _strichr, _strrichr, _memichr (and the Unicode variations: _wcsistr, _wcsichr, _wcsrichr and _wmemichr). No compatibility names since there is not much to be compatible with...

If the functionality is present, it should easy to define a macro with the name of the function to be compatible with (strcasestr, strstri, istrstr...).

Pelle
Title: stristr
Post by: JohnF on September 07, 2005, 10:33:58 PM
Quote from: "Pelle"
I have been thinking... maybe more consistent to add the following functions after all: _stristr, _strichr, _strrichr, _memichr (and the Unicode variations: _wcsistr, _wcsichr, _wcsrichr and _wmemichr). No compatibility names since there is not much to be compatible with...

If the functionality is present, it should easy to define a macro with the name of the function to be compatible with (strcasestr, strstri, istrstr...).

Pelle


Good thinking!    =D>

John
Title: Re: stristr
Post by: Mikehg on September 08, 2005, 12:15:27 AM
Quote

This seems to be a common implimentation of it.

Code: [Select]

char * _stristr(const char * szSrc, const char * cszSrch)
{
const int nLength = strlen(cszSrch);
while(*szSrc)
{
if(!_strnicmp(szSrc, cszSrch, nLength))
break;
szSrc++;
}

if(!(*szSrc))
return NULL;
else
return (char*)szSrc;
}


John


I was just recently toying with a new stristr for BCX.  What do you think about this version?
Code: [Select]

char *_stristr_(char *String, char *Pattern)
{
  int   mi=-1;
  while(Pattern[++mi])
   {
     if(String[mi]==0) return 0;
     if((String[mi]|32)!=(Pattern[mi]|32))
       { String++;  mi=-1; }
   }
  return String;
}


Mike H.
Title: stristr
Post by: JohnF on September 08, 2005, 06:37:09 AM
Mike,

Using '32' is ok for us but I wonder weather it will be ok for all language locales. I don't  know enough about other language conditions to make an informed decision. Maybe someone else knows.

John
Title: stristr
Post by: Pelle on September 08, 2005, 03:45:58 PM
If you use for example tolower(), you don't have to worry about it.

Pelle
Title: stristr
Post by: Mikehg on September 09, 2005, 02:39:29 AM
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
Title: stristr
Post by: JohnF 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
Title: stristr
Post by: Gerome 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
Title: stristr
Post by: Pelle 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
Title: stristr
Post by: JohnF 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
Title: stristr
Post by: Pelle 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
Title: stristr
Post by: JohnF 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
Title: stristr
Post by: Mikehg 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.
Title: stristr
Post by: Pelle 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
Title: stristr
Post by: Mikehg 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.
Title: Re: stristr
Post by: Robert 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

Title: Re: stristr
Post by: Pelle 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);