Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9bee682
1.11.2-alpha1
mwsis Oct 22, 2026
a5be343
test(integer_to_string): share one short performance schedule
mwsis Oct 22, 2026
1b05fd3
feature(C-string functions): added **test.performance.stlsoft.string.…
mwsis Oct 23, 2026
d487ee0
test(stlsoft): add exhaustive c_string unit tests
mwsis Oct 23, 2026
a7af6b8
fix(stlsoft): compare each strnistrn character, not only the first
mwsis Oct 23, 2026
9220332
fix(stlsoft): quiet MSVC C4310 and GCC 15 free-nonheap-object
mwsis Oct 23, 2026
1c39ac0
version
mwsis Oct 23, 2026
7fffe4d
test(stlsoft): compare a full sun_path with a counted string
mwsis Oct 23, 2026
284a2a8
perf(stlsoft): fold ASCII case in strnistrn without toupper
mwsis Oct 23, 2026
fc1d777
perf(stlsoft): fold ASCII case in strnicmp without toupper
mwsis Oct 23, 2026
3d86434
tidy
mwsis Oct 23, 2026
8de0dd7
perf(stlsoft): search ASCII strnchr with memchr
mwsis Oct 23, 2026
f48acf6
perf(stlsoft): search strnstrn with memchr and memcmp
mwsis Oct 23, 2026
db98252
tidy
mwsis Oct 23, 2026
291db12
canonicalisation
mwsis Oct 23, 2026
ed5f72b
tidy
mwsis Oct 23, 2026
96d8490
`auto_buffer` extraneous warning (#74)
synesissoftware Oct 25, 2026
387b3bf
Merge branch 'dev' into 'mem-fns'
mwsis Oct 25, 2026
7fa5410
refactor(unit-tests): applying xTests' null macros (#70)
mwsis Oct 25, 2026
9694b16
chore(nomenclature): standardise use of alpha/beta/rc nomenclature th…
synesissoftware Oct 25, 2026
5fffa1d
C-string function fixes (#77)
synesissoftware Oct 25, 2026
048a5b0
Merge branch 'dev' into 'mem-fns'
mwsis Oct 25, 2026
8e989ae
Merge branch 'master' into 'mem-fns'
mwsis Oct 25, 2026
4e19956
Merge branch 'dev' into 'mem-fns'
mwsis Oct 25, 2026
eae29bb
Merge branch 'dev' into 'mem-fns'
mwsis Oct 27, 2026
4100256
tidying
mwsis Oct 27, 2026
6796928
docs(stlsoft): summarise c_string performance by function
mwsis Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Must resolve before finalising the **1.11.3** release:
Misc:
* [ ] Bring in **include/stlsoft/string/trim_functions.h** and **test/unit/stlsoft/string/trim_functions** from `mwsis/trim_functions` (on the **STLSoft** clone);
* [ ] Bring in the `memchr` / `memcmp` and ASCII case-fold performance work for `strnchr`, `strnicmp`, `strnistrn`, and `strnstrn`, plus **test.performance.stlsoft.string.c_string**, from `mwsis/mem-fns` (on the **STLSoft** clone). The `strnistrn` correctness fix is already in **1.11.2**;
* [ ] Replace the duplicated ASCII case-fold helpers with one shared pair: `stlsoft_C_strnicmp_fold_char_m_()` / `stlsoft_C_strnistrn_fold_char_m_()`, and `stlsoft_C_strnicmp_fold_char_w_()` / `stlsoft_C_strnistrn_fold_char_w_()`;

Normalise C API (and related C-facing) identifier prefixes. **House rule**
(documented in **c-cpp-standards** → *STLSoft C API identifier prefixes*):
Expand Down
4 changes: 2 additions & 2 deletions include/stlsoft/memory/auto_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Purpose: Contains the auto_buffer template class.
*
* Created: 19th January 2002
* Updated: 23rd October 2026
* Updated: 25th October 2026
*
* Thanks: To Magnificent Imbecil for pointing out error in documentation,
* and for suggesting swap() optimisation. To Thorsten Ottosen for
Expand Down Expand Up @@ -58,7 +58,7 @@
# define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_MAJOR 5
# define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_MINOR 9
# define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_REVISION 1
# define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_EDIT 235
# define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_EDIT 236
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


Expand Down
33 changes: 30 additions & 3 deletions include/stlsoft/string/c_string/strnchr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* Purpose: Definition of stlsoft_C_strnchr() and stlsoft_C_wcsnchr()
*
* Created: 1st October 2020
* Updated: 29th September 2024
* Updated: 23rd October 2026
*
* Home: http://stlsoft.org/
*
* Copyright (c) 2020, Matthew Wilson and Synesis Information Systems
* Copyright (c) 2020-2026, Matthew Wilson and Synesis Information Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -54,7 +54,7 @@
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNCHR_MAJOR 1
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNCHR_MINOR 0
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNCHR_REVISION 2
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNCHR_EDIT 3
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNCHR_EDIT 5
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


Expand All @@ -69,6 +69,15 @@
# pragma message(__FILE__)
#endif /* STLSOFT_TRACE_INCLUDE */

#ifndef STLSOFT_INCL_H_STRING
# define STLSOFT_INCL_H_STRING
# include <string.h>
#endif /* !STLSOFT_INCL_H_STRING */
#ifndef STLSOFT_INCL_H_WCHAR
# define STLSOFT_INCL_H_WCHAR
# include <wchar.h>
#endif /* !STLSOFT_INCL_H_WCHAR */


/* /////////////////////////////////////////////////////////////////////////
* API functions
Expand All @@ -82,6 +91,13 @@ stlsoft_C_strnchr(
, int ch
)
{
/* memchr matches char promotion only when ch is in 0-127. */
if (0 <= ch &&
ch <= 127)
{
return STLSOFT_C_CAST(char const*, STLSOFT_NS_GLOBAL(memchr)(s, ch, n));
}

for (; 0 != n; --n, ++s)
{
if (ch == *s)
Expand All @@ -101,6 +117,17 @@ stlsoft_C_wcsnchr(
, int ch
)
{
/* wmemchr matches the int comparison only when ch is in 0-127. */
if (0 <= ch &&
ch <= 127)
{
return STLSOFT_NS_GLOBAL(wmemchr)(
s
, STLSOFT_C_CAST(wchar_t, ch)
, n
);
}

for (; 0 != n; --n, ++s)
{
if (ch == STLSOFT_C_CAST(int, *s))
Expand Down
97 changes: 69 additions & 28 deletions include/stlsoft/string/c_string/strnicmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* Purpose: Definition of stlsoft_C_strnicmp() and stlsoft_C_wcsnicmp()
*
* Created: 25th November 2020
* Updated: 26th October 2026
* Updated: 27th October 2026
*
* Home: http://stlsoft.org/
*
* Copyright (c) 2020-2024, Matthew Wilson and Synesis Information Systems
* Copyright (c) 2020-2026, Matthew Wilson and Synesis Information Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -53,8 +53,8 @@
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_MAJOR 1
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_MINOR 0
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_REVISION 2
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_EDIT 4
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_REVISION 3
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNICMP_EDIT 6
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


Expand All @@ -69,16 +69,59 @@
# pragma message(__FILE__)
#endif /* STLSOFT_TRACE_INCLUDE */

#ifndef STLSOFT_INCL_H_CTYPE
# define STLSOFT_INCL_H_CTYPE
# include <ctype.h>
#endif /* !STLSOFT_INCL_H_CTYPE */
#ifndef STLSOFT_INCL_H_WCTYPE
# define STLSOFT_INCL_H_WCTYPE
# include <wctype.h>
#endif /* !STLSOFT_INCL_H_WCTYPE */


/* /////////////////////////////////////////////////////////////////////////
* helpers
*/

#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION

/* ASCII letters fold by 32. Every other byte is returned unchanged. */
/* Duplicate of stlsoft_C_strnistrn_fold_char_m_(). */
STLSOFT_INLINE
int
stlsoft_C_strnicmp_fold_char_m_(
unsigned char ch
)
{
if ('a' <= ch &&
ch <= 'z')
{
ch = (unsigned char)(ch - ('a' - 'A'));
}

return (int)ch;
}

/* ASCII letters fold by 32. Units outside 0-127 use towupper. */
/* Duplicate of stlsoft_C_strnistrn_fold_char_w_(). */
STLSOFT_INLINE
int
stlsoft_C_strnicmp_fold_char_w_(
wchar_t ch
)
{
if (L'a' <= ch &&
ch <= L'z')
{
return (int)ch - (L'a' - L'A');
}

if ((unsigned long)ch <= 127ul)
{
return (int)ch;
}

return (int)STLSOFT_NS_GLOBAL(towupper)(ch);
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


/* /////////////////////////////////////////////////////////////////////////
* API functions
*/
Expand All @@ -103,23 +146,22 @@ stlsoft_C_strnicmp(
{
for (; 0 != n; --n, ++s1, ++s2)
{
int d = stlsoft_static_cast(int, *s1) - stlsoft_static_cast(int, *s2);
unsigned char const c1 = (unsigned char)*s1;
unsigned char const c2 = (unsigned char)*s2;

if (0 != d)
if (c1 != c2)
{
d = toupper(*s1) - toupper(*s2);
}
int const d = stlsoft_C_strnicmp_fold_char_m_(c1) -
stlsoft_C_strnicmp_fold_char_m_(c2);

if (0 == d)
{
if ('\0' == *s1)
if (0 != d)
{
return 0;
return d;
}
}
else
else if ('\0' == *s1)
{
return d;
return 0;
}
}

Expand All @@ -146,23 +188,22 @@ stlsoft_C_wcsnicmp(
{
for (; 0 != n; --n, ++s1, ++s2)
{
int d = stlsoft_static_cast(int, *s1) - stlsoft_static_cast(int, *s2);
wchar_t const c1 = *s1;
wchar_t const c2 = *s2;

if (0 != d)
if (c1 != c2)
{
d = towupper(*s1) - towupper(*s2);
}
int const d = stlsoft_C_strnicmp_fold_char_w_(c1) -
stlsoft_C_strnicmp_fold_char_w_(c2);

if (0 == d)
{
if ('\0' == *s1)
if (0 != d)
{
return 0;
return d;
}
}
else
else if (L'\0' == c1)
{
return d;
return 0;
}
}

Expand Down
82 changes: 70 additions & 12 deletions include/stlsoft/string/c_string/strnistrn.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Purpose: Definition of stlsoft_C_strnistrn() and stlsoft_C_wcsnistrn()
*
* Created: 1st October 2020
* Updated: 23rd October 2026
* Updated: 27th October 2026
*
* Home: http://stlsoft.org/
*
Expand Down Expand Up @@ -54,7 +54,7 @@
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNISTRN_MAJOR 1
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNISTRN_MINOR 0
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNISTRN_REVISION 4
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNISTRN_EDIT 5
# define STLSOFT_VER_STLSOFT_STRING_C_STRING_H_STRNISTRN_EDIT 6
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


Expand All @@ -69,16 +69,59 @@
# pragma message(__FILE__)
#endif /* STLSOFT_TRACE_INCLUDE */

#ifndef STLSOFT_INCL_H_CTYPE
# define STLSOFT_INCL_H_CTYPE
# include <ctype.h>
#endif /* !STLSOFT_INCL_H_CTYPE */
#ifndef STLSOFT_INCL_H_WCTYPE
# define STLSOFT_INCL_H_WCTYPE
# include <wctype.h>
#endif /* !STLSOFT_INCL_H_WCTYPE */


/* /////////////////////////////////////////////////////////////////////////
* helpers
*/

#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION

/* ASCII letters fold by 32. Every other byte is returned unchanged. */
/* Duplicate of stlsoft_C_strnicmp_fold_char_m_(). */
STLSOFT_INLINE
int
stlsoft_C_strnistrn_fold_char_m_(
unsigned char ch
)
{
if ('a' <= ch &&
ch <= 'z')
{
ch = (unsigned char)(ch - ('a' - 'A'));
}

return (int)ch;
}

/* ASCII letters fold by 32. Units outside 0-127 use towupper. */
/* Duplicate of stlsoft_C_strnicmp_fold_char_w_(). */
STLSOFT_INLINE
int
stlsoft_C_strnistrn_fold_char_w_(
wchar_t ch
)
{
if (L'a' <= ch &&
ch <= L'z')
{
return (int)ch - (L'a' - L'A');
}

if ((unsigned long)ch <= 127ul)
{
return (int)ch;
}

return (int)STLSOFT_NS_GLOBAL(towupper)(ch);
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


/* /////////////////////////////////////////////////////////////////////////
* API functions
*/
Expand Down Expand Up @@ -108,16 +151,25 @@ stlsoft_C_strnistrn(
}
else
{
unsigned char const ch0 = (unsigned char)s2[0];
int const fc0 = stlsoft_C_strnistrn_fold_char_m_(ch0);

for (; n1 >= n2; --n1, ++s1)
{
if (*s1 == *s2 ||
STLSOFT_NS_GLOBAL(toupper)(*s1) == STLSOFT_NS_GLOBAL(toupper)(*s2))
unsigned char const h0 = (unsigned char)s1[0];

if (h0 == ch0 ||
stlsoft_C_strnistrn_fold_char_m_(h0) == fc0)
{
size_t i;

for (i = 1; i != n2; ++i)
{
if (STLSOFT_NS_GLOBAL(toupper)(s1[i]) != STLSOFT_NS_GLOBAL(toupper)(s2[i]))
unsigned char const h = (unsigned char)s1[i];
unsigned char const n = (unsigned char)s2[i];

if (stlsoft_C_strnistrn_fold_char_m_(h) !=
stlsoft_C_strnistrn_fold_char_m_(n))
{
break;
}
Expand Down Expand Up @@ -159,16 +211,22 @@ stlsoft_C_wcsnistrn(
}
else
{
wchar_t const ch0 = s2[0];
int const fc0 = stlsoft_C_strnistrn_fold_char_w_(ch0);

for (; n1 >= n2; --n1, ++s1)
{
if (*s1 == *s2 ||
STLSOFT_NS_GLOBAL(towupper)(*s1) == STLSOFT_NS_GLOBAL(towupper)(*s2))
wchar_t const h0 = s1[0];

if (h0 == ch0 ||
stlsoft_C_strnistrn_fold_char_w_(h0) == fc0)
{
size_t i;

for (i = 1; i != n2; ++i)
{
if (STLSOFT_NS_GLOBAL(towupper)(s1[i]) != STLSOFT_NS_GLOBAL(towupper)(s2[i]))
if (stlsoft_C_strnistrn_fold_char_w_(s1[i]) !=
stlsoft_C_strnistrn_fold_char_w_(s2[i]))
{
break;
}
Expand Down
Loading
Loading