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
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.
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
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
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.
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.
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
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
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
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
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
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
Quote
This seems to be a common implimentation of it.
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?
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.
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
If you use for example tolower(), you don't have to worry about it.
Pelle
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
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
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
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
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
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
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
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.
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
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.
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
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);