Message ID | 20240220200445.4000158-3-adhemerval.zanella@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Improve wcsstr | expand |
Adhemerval Zanella <adhemerval.zanella@linaro.org> writes: > Parametrize test-strstr.c so it can be used to check wcsstr. LGTM although I suggest renaming one of the variables to more accurately reflect its new role. Also a question about error() formatting, but you could commit this as-is if you want. Reviewed-by: DJ Delorie <dj@redhat.com> > diff --git a/string/test-strstr.c b/string/test-strstr.c > index 05d0b7c98c..f82aeb2cfa 100644 > --- a/string/test-strstr.c > +++ b/string/test-strstr.c > @@ -17,16 +17,44 @@ > <https://www.gnu.org/licenses/>. */ > > #define TEST_MAIN > -#define TEST_NAME "strstr" > -#include "test-string.h" > +#ifndef WIDE > +# define TEST_NAME "strstr" > +#else > +# define TEST_NAME "wcsstr" > +#endif Ok. > +#ifndef WIDE > +# define CHAR char > +# define STRLEN strlen > +# define STRSTR strstr > +# define STRCPY strcpy > +# define MEMCPY memcpy > +# define MEMSET memset > +# define MEMPCPY mempcpy > +# define L(s) s > +#else > +# include <wchar.h> > +# define CHAR wchar_t > +# define STRLEN wcslen > +# define STRCPY wcscpy > +# define STRSTR wcsstr > +# define MEMCPY wmemcpy > +# define MEMSET wmemset > +# define MEMPCPY wmempcpy > +# define L(s) L ## s > +/* The test requires up to 8191 charateres, so allocate at least 32Kb > + (considering 4kb page size). */ > +# define BUF1PAGES 4 > +#endif > > +#include "test-string.h" Ok. > /* Naive implementation to verify results. */ > -static char * > -simple_strstr (const char *s1, const char *s2) > +static CHAR * > +simple_strstr (const CHAR *s1, const CHAR *s2) > { > - ssize_t s1len = strlen (s1); > - ssize_t s2len = strlen (s2); > + ssize_t s1len = STRLEN (s1); > + ssize_t s2len = STRLEN (s2); > > if (s2len > s1len) > return NULL; > @@ -38,28 +66,27 @@ simple_strstr (const char *s1, const char *s2) > if (s1[i + j] != s2[j]) > break; > if (j == s2len) > - return (char *) s1 + i; > + return (CHAR *) s1 + i; > } > > return NULL; > } Ok. > -typedef char *(*proto_t) (const char *, const char *); > +typedef CHAR *(*proto_t) (const CHAR *, const CHAR *); > > -IMPL (strstr, 1) > +IMPL (STRSTR, 1) Ok. > static int > -check_result (impl_t *impl, const char *s1, const char *s2, > - char *exp_result) > +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, > + CHAR *exp_result) Ok. > { > - char *result = CALL (impl, s1, s2); > + CHAR *result = CALL (impl, s1, s2); Ok. > if (result != exp_result) > { > - error (0, 0, "Wrong result in function %s %s %s", impl->name, > - (result == NULL) ? "(null)" : result, > - (exp_result == NULL) ? "(null)" : exp_result); > + error (0, 0, "Wrong result in function %p %p %p", impl->name, > + result, exp_result); Ok... but do we not have a way to printf() wide character strings? > @@ -68,7 +95,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, > } > > static void > -do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) > +do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, CHAR *exp_result) Ok. > @@ -79,49 +106,51 @@ static void > do_test (size_t align1, size_t align2, size_t len1, size_t len2, > int fail) > { > - char *s1 = (char *) (buf1 + align1); > - char *s2 = (char *) (buf2 + align2); > + align1 = align1 * sizeof (CHAR); > + align2 = align2 * sizeof (CHAR); > - char *ss2 = s2; > + CHAR *s1 = (CHAR *) (buf1 + align1); > + CHAR *s2 = (CHAR *) (buf2 + align2); Ok. > - static const char d[] = "1234567890abcdef"; > -#define dl (sizeof (d) - 1) > + static const CHAR d[] = L("1234567890abcdef"); > + const size_t dl = STRLEN (d); Ok. The choice of L() macro confused me at first (I read L"" instead of L("")) but it works. > + CHAR *ss2 = s2; Ok. > for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0) > { > size_t t = l > dl ? dl : l; > - ss2 = mempcpy (ss2, d, t); > + ss2 = MEMPCPY (ss2, d, t); Ok. > s2[len2] = '\0'; > > if (fail) > { > - char *ss1 = s1; > + CHAR *ss1 = s1; Ok. > for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0) > { > size_t t = l > dl ? dl : l; > - memcpy (ss1, d, t); > + MEMCPY (ss1, d, t); Ok. > - memset (s1, '0', len1); > - memcpy (s1 + len1 - len2, s2, len2); > + MEMSET (s1, '0', len1); > + MEMCPY (s1 + len1 - len2, s2, len2); Ok. > static void > check1 (void) > { > - const char s1[] = > - "F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"; > - const char s2[] = "_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"; > - char *exp_result; > + const CHAR s1[] = > + L("F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"); > + const CHAR s2[] = L("_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"); > + CHAR *exp_result; Ok. > static void > check2 (void) > { > - const char s1_stack[] = ", enable_static, \0, enable_shared, "; > + const CHAR s1_stack[] = L(", enable_static, \0, enable_shared, "); Ok. > const size_t s1_byte_count = 18; I think this needs to be renamed to s1_char_count or something, since with wide characters, S1 is no longer 18 bytes long. > - const char *s2_stack = &(s1_stack[s1_byte_count]); > - const size_t s2_byte_count = 18; > - char *exp_result; > + const size_t s1_byte_len = 18 * sizeof (CHAR); > + const CHAR *s2_stack = &(s1_stack[s1_byte_count]); > + const size_t s2_byte_len = 18 * sizeof (CHAR);; > + CHAR *exp_result; Ok. > /* Haystack at end of page. The following page is protected. */ > - char *s1_page_end = (void *) buf1 + page_size - s1_byte_count; > - strcpy (s1_page_end, s1_stack); > + CHAR *s1_page_end = (void *) buf1 + page_size - s1_byte_len; > + STRCPY (s1_page_end, s1_stack); Ok. > /* Haystack which crosses a page boundary. > Note: page_size is at least 2 * getpagesize. See test_init. */ > - char *s1_page_cross = (void *) buf1 + page_size_real - 8; > - strcpy (s1_page_cross, s1_stack); > + CHAR *s1_page_cross = (void *) buf1 + page_size_real - 8; > + STRCPY (s1_page_cross, s1_stack); Ok. > /* Needle at end of page. The following page is protected. */ > - char *s2_page_end = (void *) buf2 + page_size - s2_byte_count; > - strcpy (s2_page_end, s2_stack); > + CHAR *s2_page_end = (void *) buf2 + page_size - s2_byte_len; > + STRCPY (s2_page_end, s2_stack); Ok. > /* Needle which crosses a page boundary. > Note: page_size is at least 2 * getpagesize. See test_init. */ > - char *s2_page_cross = (void *) buf2 + page_size_real - 8; > - strcpy (s2_page_cross, s2_stack); > + CHAR *s2_page_cross = (void *) buf2 + page_size_real - 8; > + STRCPY (s2_page_cross, s2_stack); Ok. > static void > pr23637 (void) > { > - char *h = (char*) buf1; > - char *n = (char*) buf2; > + CHAR *h = (CHAR*) buf1; > + CHAR *n = (CHAR*) buf2; Ok. > - char *exp_result = simple_strstr (h, n); > + CHAR *exp_result = simple_strstr (h, n); Ok. > diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile > + test-wcsstr \ Ok. > diff --git a/wcsmbs/test-wcsstr.c b/wcsmbs/test-wcsstr.c > +/* Test wcsstr function. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#define WIDE 1 > +#include <string/test-strstr.c> Ok.
On 28/02/24 21:45, DJ Delorie wrote: > Adhemerval Zanella <adhemerval.zanella@linaro.org> writes: >> Parametrize test-strstr.c so it can be used to check wcsstr. > > LGTM although I suggest renaming one of the variables to more accurately > reflect its new role. Also a question about error() formatting, but you > could commit this as-is if you want. > > Reviewed-by: DJ Delorie <dj@redhat.com> > >> diff --git a/string/test-strstr.c b/string/test-strstr.c >> index 05d0b7c98c..f82aeb2cfa 100644 >> --- a/string/test-strstr.c >> +++ b/string/test-strstr.c >> @@ -17,16 +17,44 @@ >> <https://www.gnu.org/licenses/>. */ >> >> #define TEST_MAIN >> -#define TEST_NAME "strstr" >> -#include "test-string.h" >> +#ifndef WIDE >> +# define TEST_NAME "strstr" >> +#else >> +# define TEST_NAME "wcsstr" >> +#endif > > Ok. > >> +#ifndef WIDE >> +# define CHAR char >> +# define STRLEN strlen >> +# define STRSTR strstr >> +# define STRCPY strcpy >> +# define MEMCPY memcpy >> +# define MEMSET memset >> +# define MEMPCPY mempcpy >> +# define L(s) s >> +#else >> +# include <wchar.h> >> +# define CHAR wchar_t >> +# define STRLEN wcslen >> +# define STRCPY wcscpy >> +# define STRSTR wcsstr >> +# define MEMCPY wmemcpy >> +# define MEMSET wmemset >> +# define MEMPCPY wmempcpy >> +# define L(s) L ## s >> +/* The test requires up to 8191 charateres, so allocate at least 32Kb >> + (considering 4kb page size). */ >> +# define BUF1PAGES 4 >> +#endif >> >> +#include "test-string.h" > > Ok. > >> /* Naive implementation to verify results. */ >> -static char * >> -simple_strstr (const char *s1, const char *s2) >> +static CHAR * >> +simple_strstr (const CHAR *s1, const CHAR *s2) >> { >> - ssize_t s1len = strlen (s1); >> - ssize_t s2len = strlen (s2); >> + ssize_t s1len = STRLEN (s1); >> + ssize_t s2len = STRLEN (s2); >> >> if (s2len > s1len) >> return NULL; >> @@ -38,28 +66,27 @@ simple_strstr (const char *s1, const char *s2) >> if (s1[i + j] != s2[j]) >> break; >> if (j == s2len) >> - return (char *) s1 + i; >> + return (CHAR *) s1 + i; >> } >> >> return NULL; >> } > > Ok. > > >> -typedef char *(*proto_t) (const char *, const char *); >> +typedef CHAR *(*proto_t) (const CHAR *, const CHAR *); >> >> -IMPL (strstr, 1) >> +IMPL (STRSTR, 1) > > Ok. > >> static int >> -check_result (impl_t *impl, const char *s1, const char *s2, >> - char *exp_result) >> +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, >> + CHAR *exp_result) > > Ok. > >> { >> - char *result = CALL (impl, s1, s2); >> + CHAR *result = CALL (impl, s1, s2); > > Ok. > >> if (result != exp_result) >> { >> - error (0, 0, "Wrong result in function %s %s %s", impl->name, >> - (result == NULL) ? "(null)" : result, >> - (exp_result == NULL) ? "(null)" : exp_result); >> + error (0, 0, "Wrong result in function %p %p %p", impl->name, >> + result, exp_result); > > Ok... but do we not have a way to printf() wide character strings? Indeed, I think we can use "%Ls" here. I think I have used %p just to avoid adding another parametrized macro. I will fix it. > >> @@ -68,7 +95,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, >> } >> >> static void >> -do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) >> +do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, CHAR *exp_result) > > Ok. > >> @@ -79,49 +106,51 @@ static void >> do_test (size_t align1, size_t align2, size_t len1, size_t len2, >> int fail) >> { >> - char *s1 = (char *) (buf1 + align1); >> - char *s2 = (char *) (buf2 + align2); >> + align1 = align1 * sizeof (CHAR); >> + align2 = align2 * sizeof (CHAR); >> - char *ss2 = s2; >> + CHAR *s1 = (CHAR *) (buf1 + align1); >> + CHAR *s2 = (CHAR *) (buf2 + align2); > > Ok. > >> - static const char d[] = "1234567890abcdef"; >> -#define dl (sizeof (d) - 1) >> + static const CHAR d[] = L("1234567890abcdef"); >> + const size_t dl = STRLEN (d); > > Ok. The choice of L() macro confused me at first (I read L"" instead of > L("")) but it works. > >> + CHAR *ss2 = s2; > > Ok. > >> for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0) >> { >> size_t t = l > dl ? dl : l; >> - ss2 = mempcpy (ss2, d, t); >> + ss2 = MEMPCPY (ss2, d, t); > > Ok. > >> s2[len2] = '\0'; >> >> if (fail) >> { >> - char *ss1 = s1; >> + CHAR *ss1 = s1; > > Ok. > >> for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0) >> { >> size_t t = l > dl ? dl : l; >> - memcpy (ss1, d, t); >> + MEMCPY (ss1, d, t); > > Ok. > >> - memset (s1, '0', len1); >> - memcpy (s1 + len1 - len2, s2, len2); >> + MEMSET (s1, '0', len1); >> + MEMCPY (s1 + len1 - len2, s2, len2); > > Ok. > >> static void >> check1 (void) >> { >> - const char s1[] = >> - "F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"; >> - const char s2[] = "_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"; >> - char *exp_result; >> + const CHAR s1[] = >> + L("F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"); >> + const CHAR s2[] = L("_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"); >> + CHAR *exp_result; > > Ok. > >> static void >> check2 (void) >> { >> - const char s1_stack[] = ", enable_static, \0, enable_shared, "; >> + const CHAR s1_stack[] = L(", enable_static, \0, enable_shared, "); > > Ok. > >> const size_t s1_byte_count = 18; > > I think this needs to be renamed to s1_char_count or something, since > with wide characters, S1 is no longer 18 bytes long. Ack. > >> - const char *s2_stack = &(s1_stack[s1_byte_count]); >> - const size_t s2_byte_count = 18; >> - char *exp_result; >> + const size_t s1_byte_len = 18 * sizeof (CHAR); >> + const CHAR *s2_stack = &(s1_stack[s1_byte_count]); >> + const size_t s2_byte_len = 18 * sizeof (CHAR);; >> + CHAR *exp_result; > > Ok. > >> /* Haystack at end of page. The following page is protected. */ >> - char *s1_page_end = (void *) buf1 + page_size - s1_byte_count; >> - strcpy (s1_page_end, s1_stack); >> + CHAR *s1_page_end = (void *) buf1 + page_size - s1_byte_len; >> + STRCPY (s1_page_end, s1_stack); > > Ok. > >> /* Haystack which crosses a page boundary. >> Note: page_size is at least 2 * getpagesize. See test_init. */ >> - char *s1_page_cross = (void *) buf1 + page_size_real - 8; >> - strcpy (s1_page_cross, s1_stack); >> + CHAR *s1_page_cross = (void *) buf1 + page_size_real - 8; >> + STRCPY (s1_page_cross, s1_stack); > > Ok. > >> /* Needle at end of page. The following page is protected. */ >> - char *s2_page_end = (void *) buf2 + page_size - s2_byte_count; >> - strcpy (s2_page_end, s2_stack); >> + CHAR *s2_page_end = (void *) buf2 + page_size - s2_byte_len; >> + STRCPY (s2_page_end, s2_stack); > > Ok. > >> /* Needle which crosses a page boundary. >> Note: page_size is at least 2 * getpagesize. See test_init. */ >> - char *s2_page_cross = (void *) buf2 + page_size_real - 8; >> - strcpy (s2_page_cross, s2_stack); >> + CHAR *s2_page_cross = (void *) buf2 + page_size_real - 8; >> + STRCPY (s2_page_cross, s2_stack); > > Ok. > >> static void >> pr23637 (void) >> { >> - char *h = (char*) buf1; >> - char *n = (char*) buf2; >> + CHAR *h = (CHAR*) buf1; >> + CHAR *n = (CHAR*) buf2; > > Ok. > >> - char *exp_result = simple_strstr (h, n); >> + CHAR *exp_result = simple_strstr (h, n); > > Ok. > >> diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile >> + test-wcsstr \ > > Ok. > >> diff --git a/wcsmbs/test-wcsstr.c b/wcsmbs/test-wcsstr.c >> +/* Test wcsstr function. >> + Copyright (C) 2024 Free Software Foundation, Inc. >> + This file is part of the GNU C Library. >> + >> + The GNU C Library is free software; you can redistribute it and/or >> + modify it under the terms of the GNU Lesser General Public >> + License as published by the Free Software Foundation; either >> + version 2.1 of the License, or (at your option) any later version. >> + >> + The GNU C Library is distributed in the hope that it will be useful, >> + but WITHOUT ANY WARRANTY; without even the implied warranty of >> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + Lesser General Public License for more details. >> + >> + You should have received a copy of the GNU Lesser General Public >> + License along with the GNU C Library; if not, see >> + <https://www.gnu.org/licenses/>. */ >> + >> +#define WIDE 1 >> +#include <string/test-strstr.c> > > Ok. >
On 01/03/24 12:52, Adhemerval Zanella Netto wrote: > > > On 28/02/24 21:45, DJ Delorie wrote: >> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes: >>> Parametrize test-strstr.c so it can be used to check wcsstr. >> >> LGTM although I suggest renaming one of the variables to more accurately >> reflect its new role. Also a question about error() formatting, but you >> could commit this as-is if you want. >> >> Reviewed-by: DJ Delorie <dj@redhat.com> >> >>> diff --git a/string/test-strstr.c b/string/test-strstr.c >>> index 05d0b7c98c..f82aeb2cfa 100644 >>> --- a/string/test-strstr.c >>> +++ b/string/test-strstr.c >>> @@ -17,16 +17,44 @@ >>> <https://www.gnu.org/licenses/>. */ >>> >>> #define TEST_MAIN >>> -#define TEST_NAME "strstr" >>> -#include "test-string.h" >>> +#ifndef WIDE >>> +# define TEST_NAME "strstr" >>> +#else >>> +# define TEST_NAME "wcsstr" >>> +#endif >> >> Ok. >> >>> +#ifndef WIDE >>> +# define CHAR char >>> +# define STRLEN strlen >>> +# define STRSTR strstr >>> +# define STRCPY strcpy >>> +# define MEMCPY memcpy >>> +# define MEMSET memset >>> +# define MEMPCPY mempcpy >>> +# define L(s) s >>> +#else >>> +# include <wchar.h> >>> +# define CHAR wchar_t >>> +# define STRLEN wcslen >>> +# define STRCPY wcscpy >>> +# define STRSTR wcsstr >>> +# define MEMCPY wmemcpy >>> +# define MEMSET wmemset >>> +# define MEMPCPY wmempcpy >>> +# define L(s) L ## s >>> +/* The test requires up to 8191 charateres, so allocate at least 32Kb >>> + (considering 4kb page size). */ >>> +# define BUF1PAGES 4 >>> +#endif >>> >>> +#include "test-string.h" >> >> Ok. >> >>> /* Naive implementation to verify results. */ >>> -static char * >>> -simple_strstr (const char *s1, const char *s2) >>> +static CHAR * >>> +simple_strstr (const CHAR *s1, const CHAR *s2) >>> { >>> - ssize_t s1len = strlen (s1); >>> - ssize_t s2len = strlen (s2); >>> + ssize_t s1len = STRLEN (s1); >>> + ssize_t s2len = STRLEN (s2); >>> >>> if (s2len > s1len) >>> return NULL; >>> @@ -38,28 +66,27 @@ simple_strstr (const char *s1, const char *s2) >>> if (s1[i + j] != s2[j]) >>> break; >>> if (j == s2len) >>> - return (char *) s1 + i; >>> + return (CHAR *) s1 + i; >>> } >>> >>> return NULL; >>> } >> >> Ok. >> >> >>> -typedef char *(*proto_t) (const char *, const char *); >>> +typedef CHAR *(*proto_t) (const CHAR *, const CHAR *); >>> >>> -IMPL (strstr, 1) >>> +IMPL (STRSTR, 1) >> >> Ok. >> >>> static int >>> -check_result (impl_t *impl, const char *s1, const char *s2, >>> - char *exp_result) >>> +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, >>> + CHAR *exp_result) >> >> Ok. >> >>> { >>> - char *result = CALL (impl, s1, s2); >>> + CHAR *result = CALL (impl, s1, s2); >> >> Ok. >> >>> if (result != exp_result) >>> { >>> - error (0, 0, "Wrong result in function %s %s %s", impl->name, >>> - (result == NULL) ? "(null)" : result, >>> - (exp_result == NULL) ? "(null)" : exp_result); >>> + error (0, 0, "Wrong result in function %p %p %p", impl->name, >>> + result, exp_result); >> >> Ok... but do we not have a way to printf() wide character strings? > > Indeed, I think we can use "%Ls" here. I think I have used %p just to avoid > adding another parametrized macro. I will fix it. In fact I think I will keep '%p', the others tests functions also only print the address (I think to avoid polluting the console/log file with gibberish).
diff --git a/string/test-strstr.c b/string/test-strstr.c index 05d0b7c98c..f82aeb2cfa 100644 --- a/string/test-strstr.c +++ b/string/test-strstr.c @@ -17,16 +17,44 @@ <https://www.gnu.org/licenses/>. */ #define TEST_MAIN -#define TEST_NAME "strstr" -#include "test-string.h" +#ifndef WIDE +# define TEST_NAME "strstr" +#else +# define TEST_NAME "wcsstr" +#endif + +#ifndef WIDE +# define CHAR char +# define STRLEN strlen +# define STRSTR strstr +# define STRCPY strcpy +# define MEMCPY memcpy +# define MEMSET memset +# define MEMPCPY mempcpy +# define L(s) s +#else +# include <wchar.h> +# define CHAR wchar_t +# define STRLEN wcslen +# define STRCPY wcscpy +# define STRSTR wcsstr +# define MEMCPY wmemcpy +# define MEMSET wmemset +# define MEMPCPY wmempcpy +# define L(s) L ## s +/* The test requires up to 8191 charateres, so allocate at least 32Kb + (considering 4kb page size). */ +# define BUF1PAGES 4 +#endif +#include "test-string.h" /* Naive implementation to verify results. */ -static char * -simple_strstr (const char *s1, const char *s2) +static CHAR * +simple_strstr (const CHAR *s1, const CHAR *s2) { - ssize_t s1len = strlen (s1); - ssize_t s2len = strlen (s2); + ssize_t s1len = STRLEN (s1); + ssize_t s2len = STRLEN (s2); if (s2len > s1len) return NULL; @@ -38,28 +66,27 @@ simple_strstr (const char *s1, const char *s2) if (s1[i + j] != s2[j]) break; if (j == s2len) - return (char *) s1 + i; + return (CHAR *) s1 + i; } return NULL; } -typedef char *(*proto_t) (const char *, const char *); +typedef CHAR *(*proto_t) (const CHAR *, const CHAR *); -IMPL (strstr, 1) +IMPL (STRSTR, 1) static int -check_result (impl_t *impl, const char *s1, const char *s2, - char *exp_result) +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, + CHAR *exp_result) { - char *result = CALL (impl, s1, s2); + CHAR *result = CALL (impl, s1, s2); if (result != exp_result) { - error (0, 0, "Wrong result in function %s %s %s", impl->name, - (result == NULL) ? "(null)" : result, - (exp_result == NULL) ? "(null)" : exp_result); + error (0, 0, "Wrong result in function %p %p %p", impl->name, + result, exp_result); ret = 1; return -1; } @@ -68,7 +95,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, } static void -do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) +do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, CHAR *exp_result) { if (check_result (impl, s1, s2, exp_result) < 0) return; @@ -79,49 +106,51 @@ static void do_test (size_t align1, size_t align2, size_t len1, size_t len2, int fail) { - char *s1 = (char *) (buf1 + align1); - char *s2 = (char *) (buf2 + align2); + align1 = align1 * sizeof (CHAR); + align2 = align2 * sizeof (CHAR); - static const char d[] = "1234567890abcdef"; -#define dl (sizeof (d) - 1) - char *ss2 = s2; + CHAR *s1 = (CHAR *) (buf1 + align1); + CHAR *s2 = (CHAR *) (buf2 + align2); + + static const CHAR d[] = L("1234567890abcdef"); + const size_t dl = STRLEN (d); + CHAR *ss2 = s2; for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0) { size_t t = l > dl ? dl : l; - ss2 = mempcpy (ss2, d, t); + ss2 = MEMPCPY (ss2, d, t); } s2[len2] = '\0'; if (fail) { - char *ss1 = s1; + CHAR *ss1 = s1; for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0) { size_t t = l > dl ? dl : l; - memcpy (ss1, d, t); + MEMCPY (ss1, d, t); ++ss1[len2 > 7 ? 7 : len2 - 1]; ss1 += t; } } else { - memset (s1, '0', len1); - memcpy (s1 + len1 - len2, s2, len2); + MEMSET (s1, '0', len1); + MEMCPY (s1 + len1 - len2, s2, len2); } s1[len1] = '\0'; FOR_EACH_IMPL (impl, 0) do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2); - } static void check1 (void) { - const char s1[] = - "F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"; - const char s2[] = "_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"; - char *exp_result; + const CHAR s1[] = + L("F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD"); + const CHAR s2[] = L("_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD"); + CHAR *exp_result; exp_result = simple_strstr (s1, s2); FOR_EACH_IMPL (impl, 0) @@ -131,30 +160,31 @@ check1 (void) static void check2 (void) { - const char s1_stack[] = ", enable_static, \0, enable_shared, "; + const CHAR s1_stack[] = L(", enable_static, \0, enable_shared, "); const size_t s1_byte_count = 18; - const char *s2_stack = &(s1_stack[s1_byte_count]); - const size_t s2_byte_count = 18; - char *exp_result; + const size_t s1_byte_len = 18 * sizeof (CHAR); + const CHAR *s2_stack = &(s1_stack[s1_byte_count]); + const size_t s2_byte_len = 18 * sizeof (CHAR);; + CHAR *exp_result; const size_t page_size_real = getpagesize (); /* Haystack at end of page. The following page is protected. */ - char *s1_page_end = (void *) buf1 + page_size - s1_byte_count; - strcpy (s1_page_end, s1_stack); + CHAR *s1_page_end = (void *) buf1 + page_size - s1_byte_len; + STRCPY (s1_page_end, s1_stack); /* Haystack which crosses a page boundary. Note: page_size is at least 2 * getpagesize. See test_init. */ - char *s1_page_cross = (void *) buf1 + page_size_real - 8; - strcpy (s1_page_cross, s1_stack); + CHAR *s1_page_cross = (void *) buf1 + page_size_real - 8; + STRCPY (s1_page_cross, s1_stack); /* Needle at end of page. The following page is protected. */ - char *s2_page_end = (void *) buf2 + page_size - s2_byte_count; - strcpy (s2_page_end, s2_stack); + CHAR *s2_page_end = (void *) buf2 + page_size - s2_byte_len; + STRCPY (s2_page_end, s2_stack); /* Needle which crosses a page boundary. Note: page_size is at least 2 * getpagesize. See test_init. */ - char *s2_page_cross = (void *) buf2 + page_size_real - 8; - strcpy (s2_page_cross, s2_stack); + CHAR *s2_page_cross = (void *) buf2 + page_size_real - 8; + STRCPY (s2_page_cross, s2_stack); exp_result = simple_strstr (s1_stack, s2_stack); FOR_EACH_IMPL (impl, 0) @@ -178,8 +208,8 @@ check2 (void) static void pr23637 (void) { - char *h = (char*) buf1; - char *n = (char*) buf2; + CHAR *h = (CHAR*) buf1; + CHAR *n = (CHAR*) buf2; for (int i = 0; i < N; i++) { @@ -194,7 +224,7 @@ pr23637 (void) /* Ensure we don't match at the first 'x'. */ h[0] = 'x'; - char *exp_result = simple_strstr (h, n); + CHAR *exp_result = simple_strstr (h, n); FOR_EACH_IMPL (impl, 0) check_result (impl, h, n, exp_result); } diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile index f3333c6a4b..1cddd8cc6d 100644 --- a/wcsmbs/Makefile +++ b/wcsmbs/Makefile @@ -163,6 +163,7 @@ tests := \ test-wcspbrk \ test-wcsrchr \ test-wcsspn \ + test-wcsstr \ test-wmemchr \ test-wmemcmp \ test-wmemset \ diff --git a/wcsmbs/test-wcsstr.c b/wcsmbs/test-wcsstr.c new file mode 100644 index 0000000000..23d6517255 --- /dev/null +++ b/wcsmbs/test-wcsstr.c @@ -0,0 +1,20 @@ +/* Test wcsstr function. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#define WIDE 1 +#include <string/test-strstr.c>