For many years, I know about the Java functions String.startsWith and String.endsWith and how easy they are to use, compared to the 3-argument strncmp. And nevertheless I thought that in C, we are all expert programmers, we don't need one-liner abstractions.
And now I see that six years ago, I wrote code like this: (strlen (term) > 8 && strcmp (term + strlen (term) - 8, "-direct") == 0)) Code that doesn't work. Obviously? No, not obviously. The one-liner abstractions would have avoided this mistake. Let me add these functions to Gnulib, so we can make some of these idioms more maintainable. Regarding the function names: Some packages use 'strstartswith' and 'strendswith'. I believe the added underscore makes the function name slightly more readable. 2025-01-03 Bruno Haible <br...@clisp.org> tests: Use str_endswith. * tests/test-canonicalize.c (main): Use str_endswith. * tests/test-canonicalize-lgpl.c (main): Likewise. * tests/test-setlocale-w32utf8.c (main): Likewise. * modules/canonicalize-tests (Depends-on): Add str_endswith. * modules/canonicalize-lgpl-tests (Depends-on): Likewise. * modules/setlocale-tests (Depends-on): Likewise. gen-uni-tables, get-rusage-data, isatty: Use str_endswith. * lib/gen-uni-tables.c (fill_attributes): Use str_endswith. * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise. * lib/isatty.c (IsCygwinConsoleHandle): Likewise. * modules/gen-uni-tables (Depends-on): Add str_endswith. * modules/get-rusage-data (Depends-on): Likewise. * modules/isatty (Depends-on): Likewise. 2025-01-03 Bruno Haible <br...@clisp.org> tests: Use str_startswith. * tests/test-environ.c (main): Use str_startswith. * tests/test-getprogname.c (main): Likewise. * tests/test-libtextstyle.c (main): Likewise. * tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise. * modules/environ-tests (Depends-on): Add str_startswith. * modules/getprogname-tests (Depends-on): Likewise. * modules/libtextstyle-optional-tests (Depends-on): Likewise. * modules/strsignal-tests (Depends-on): Likewise. git-merge-changelog, gen-uni-tables: Use str_startswith. * lib/git-merge-changelog.c (main): Use str_startswith. * lib/gen-uni-tables.c (output_predicate, is_property_composite, is_nonspacing): Likewise. * modules/git-merge-changelog (Depends-on): Add str_startswith. * modules/gen-uni-tables (Depends-on): Likewise. 2025-01-03 Bruno Haible <br...@clisp.org> str_endswith: Add tests. * tests/test-str_endswith.c: New file. * modules/str_endswith-tests: New file. str_endswith: New module. * lib/string.in.h (str_endswith): New declaration. * lib/str_endswith.c: New file. * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STR_ENDSWITH. * modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH. * modules/str_endswith: New file. 2025-01-03 Bruno Haible <br...@clisp.org> str_startswith: Add tests. * tests/test-str_startswith.c: New file. * modules/str_startswith-tests: New file. str_startswith: New module. * lib/string.in.h (str_startswith): New declaration. * lib/str_startswith.c: New file. * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STR_STARTSWITH. * modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH. * modules/str_startswith: New file.
>From 24010120fab36721caaf92be076655571e44da07 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 09:26:14 +0100 Subject: [PATCH 1/8] str_startswith: New module. * lib/string.in.h (str_startswith): New declaration. * lib/str_startswith.c: New file. * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STR_STARTSWITH. * modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH. * modules/str_startswith: New file. --- ChangeLog | 10 ++++++++++ lib/str_startswith.c | 29 +++++++++++++++++++++++++++++ lib/string.in.h | 8 ++++++++ m4/string_h.m4 | 3 ++- modules/str_startswith | 23 +++++++++++++++++++++++ modules/string-h | 1 + 6 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 lib/str_startswith.c create mode 100644 modules/str_startswith diff --git a/ChangeLog b/ChangeLog index 8853983620..be756cd8ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-01-03 Bruno Haible <br...@clisp.org> + + str_startswith: New module. + * lib/string.in.h (str_startswith): New declaration. + * lib/str_startswith.c: New file. + * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize + GNULIB_STR_STARTSWITH. + * modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH. + * modules/str_startswith: New file. + 2025-01-02 Bruno Haible <br...@clisp.org> gnulib-l10n: Clarify the license of the POT file. diff --git a/lib/str_startswith.c b/lib/str_startswith.c new file mode 100644 index 0000000000..381236ec2a --- /dev/null +++ b/lib/str_startswith.c @@ -0,0 +1,29 @@ +/* str_startswith function. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <br...@clisp.org>, 2025. */ + +#include "config.h" + +/* Specification. */ +#include <string.h> + + +int +str_startswith (const char *string, const char *prefix) +{ + return strncmp (string, prefix, strlen (prefix)) == 0; +} diff --git a/lib/string.in.h b/lib/string.in.h index 1bae32ad46..b8b388abad 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -1077,6 +1077,14 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " /* The following functions are not specified by POSIX. They are gnulib extensions. */ +#if @GNULIB_STR_STARTSWITH@ +/* Returns true if STRING starts with PREFIX. + Returns false otherwise. */ +_GL_EXTERN_C int str_startswith (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + #if @GNULIB_MBSLEN@ /* Return the number of multibyte characters in the character string STRING. This considers multibyte characters, unlike strlen, which counts bytes. */ diff --git a/m4/string_h.m4 b/m4/string_h.m4 index a07738479d..bda7894cfe 100644 --- a/m4/string_h.m4 +++ b/m4/string_h.m4 @@ -1,5 +1,5 @@ # string_h.m4 -# serial 39 +# serial 40 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -70,6 +70,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS] gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRSTR]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR]) diff --git a/modules/str_startswith b/modules/str_startswith new file mode 100644 index 0000000000..4b1754e341 --- /dev/null +++ b/modules/str_startswith @@ -0,0 +1,23 @@ +Description: +str_startswith() function: test whether a string starts with a given prefix. + +Files: +lib/str_startswith.c + +Depends-on: +string-h + +configure.ac: +gl_STRING_MODULE_INDICATOR([str_startswith]) + +Makefile.am: +lib_SOURCES += str_startswith.c + +Include: +<string.h> + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/string-h b/modules/string-h index 0dfa096cc8..2dba436c7e 100644 --- a/modules/string-h +++ b/modules/string-h @@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \ -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ -e 's/@''GNULIB_STRERRORNAME_NP''@/$(GNULIB_STRERRORNAME_NP)/g' \ -- 2.43.0
>From 2508f39d60797ab024c69b0f5bb2fcaa67ab3e42 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 09:33:01 +0100 Subject: [PATCH 2/8] str_startswith: Add tests. * tests/test-str_startswith.c: New file. * modules/str_startswith-tests: New file. --- ChangeLog | 4 ++++ modules/str_startswith-tests | 11 +++++++++ tests/test-str_startswith.c | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 modules/str_startswith-tests create mode 100644 tests/test-str_startswith.c diff --git a/ChangeLog b/ChangeLog index be756cd8ee..d4a2721715 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2025-01-03 Bruno Haible <br...@clisp.org> + str_startswith: Add tests. + * tests/test-str_startswith.c: New file. + * modules/str_startswith-tests: New file. + str_startswith: New module. * lib/string.in.h (str_startswith): New declaration. * lib/str_startswith.c: New file. diff --git a/modules/str_startswith-tests b/modules/str_startswith-tests new file mode 100644 index 0000000000..9239b55a42 --- /dev/null +++ b/modules/str_startswith-tests @@ -0,0 +1,11 @@ +Files: +tests/test-str_startswith.c +tests/macros.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-str_startswith +check_PROGRAMS += test-str_startswith diff --git a/tests/test-str_startswith.c b/tests/test-str_startswith.c new file mode 100644 index 0000000000..5dd741ae4c --- /dev/null +++ b/tests/test-str_startswith.c @@ -0,0 +1,43 @@ +/* Test of str_startswith() function. + Copyright (C) 2025 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#include "macros.h" + +int +main () +{ + ASSERT (str_startswith ("", "")); + ASSERT (str_startswith ("abc", "")); + + ASSERT (!str_startswith ("", "a")); + ASSERT (!str_startswith ("x", "a")); + ASSERT (str_startswith ("a", "a")); + ASSERT (str_startswith ("abc", "a")); + + ASSERT (!str_startswith ("", "xyz")); + ASSERT (!str_startswith ("x", "xyz")); + ASSERT (!str_startswith ("a", "xyz")); + ASSERT (!str_startswith ("abc", "xyz")); + ASSERT (str_startswith ("xyz", "xyz")); + ASSERT (str_startswith ("xyzzy", "xyz")); + + return test_exit_status; +} -- 2.43.0
>From d89ac9373d9748f7601babf52c9129fcbcf0c907 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 09:54:14 +0100 Subject: [PATCH 3/8] str_endswith: New module. * lib/string.in.h (str_endswith): New declaration. * lib/str_endswith.c: New file. * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STR_ENDSWITH. * modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH. * modules/str_endswith: New file. --- ChangeLog | 10 ++++++++++ lib/str_endswith.c | 31 +++++++++++++++++++++++++++++++ lib/string.in.h | 8 ++++++++ m4/string_h.m4 | 3 ++- modules/str_endswith | 23 +++++++++++++++++++++++ modules/string-h | 1 + 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 lib/str_endswith.c create mode 100644 modules/str_endswith diff --git a/ChangeLog b/ChangeLog index d4a2721715..3172894f30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-01-03 Bruno Haible <br...@clisp.org> + + str_endswith: New module. + * lib/string.in.h (str_endswith): New declaration. + * lib/str_endswith.c: New file. + * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize + GNULIB_STR_ENDSWITH. + * modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH. + * modules/str_endswith: New file. + 2025-01-03 Bruno Haible <br...@clisp.org> str_startswith: Add tests. diff --git a/lib/str_endswith.c b/lib/str_endswith.c new file mode 100644 index 0000000000..f33ac6997c --- /dev/null +++ b/lib/str_endswith.c @@ -0,0 +1,31 @@ +/* str_endswith function. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <br...@clisp.org>, 2025. */ + +#include "config.h" + +/* Specification. */ +#include <string.h> + + +int +str_endswith (const char *string, const char *suffix) +{ + size_t len = strlen (string); + size_t n = strlen (suffix); + return len >= n && strcmp (string + len - n, suffix) == 0; +} diff --git a/lib/string.in.h b/lib/string.in.h index b8b388abad..f11b8f5706 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -1085,6 +1085,14 @@ _GL_EXTERN_C int str_startswith (const char *string, const char *prefix) _GL_ARG_NONNULL ((1, 2)); #endif +#if @GNULIB_STR_ENDSWITH@ +/* Returns true if STRING ends with SUFFIX. + Returns false otherwise. */ +_GL_EXTERN_C int str_endswith (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + #if @GNULIB_MBSLEN@ /* Return the number of multibyte characters in the character string STRING. This considers multibyte characters, unlike strlen, which counts bytes. */ diff --git a/m4/string_h.m4 b/m4/string_h.m4 index bda7894cfe..d2adb95bad 100644 --- a/m4/string_h.m4 +++ b/m4/string_h.m4 @@ -1,5 +1,5 @@ # string_h.m4 -# serial 40 +# serial 41 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -71,6 +71,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS] gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_ENDSWITH]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR]) diff --git a/modules/str_endswith b/modules/str_endswith new file mode 100644 index 0000000000..c04b2c8eb0 --- /dev/null +++ b/modules/str_endswith @@ -0,0 +1,23 @@ +Description: +str_endswith() function: test whether a string ends with a given suffix. + +Files: +lib/str_endswith.c + +Depends-on: +string-h + +configure.ac: +gl_STRING_MODULE_INDICATOR([str_endswith]) + +Makefile.am: +lib_SOURCES += str_endswith.c + +Include: +<string.h> + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/string-h b/modules/string-h index 2dba436c7e..0897afe206 100644 --- a/modules/string-h +++ b/modules/string-h @@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STR_ENDSWITH''@/$(GNULIB_STR_ENDSWITH)/g' \ -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \ -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ -- 2.43.0
>From 5a50792e2f1f5fe83c4df68f62819a4b7c9e0fa1 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 09:59:56 +0100 Subject: [PATCH 4/8] str_endswith: Add tests. * tests/test-str_endswith.c: New file. * modules/str_endswith-tests: New file. --- ChangeLog | 4 ++++ modules/str_endswith-tests | 11 ++++++++++ tests/test-str_endswith.c | 43 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 modules/str_endswith-tests create mode 100644 tests/test-str_endswith.c diff --git a/ChangeLog b/ChangeLog index 3172894f30..b57ea5cae1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2025-01-03 Bruno Haible <br...@clisp.org> + str_endswith: Add tests. + * tests/test-str_endswith.c: New file. + * modules/str_endswith-tests: New file. + str_endswith: New module. * lib/string.in.h (str_endswith): New declaration. * lib/str_endswith.c: New file. diff --git a/modules/str_endswith-tests b/modules/str_endswith-tests new file mode 100644 index 0000000000..ef8990c026 --- /dev/null +++ b/modules/str_endswith-tests @@ -0,0 +1,11 @@ +Files: +tests/test-str_endswith.c +tests/macros.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-str_endswith +check_PROGRAMS += test-str_endswith diff --git a/tests/test-str_endswith.c b/tests/test-str_endswith.c new file mode 100644 index 0000000000..fc1ec0abfc --- /dev/null +++ b/tests/test-str_endswith.c @@ -0,0 +1,43 @@ +/* Test of str_endswith() function. + Copyright (C) 2025 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#include "macros.h" + +int +main () +{ + ASSERT (str_endswith ("", "")); + ASSERT (str_endswith ("abc", "")); + + ASSERT (!str_endswith ("", "c")); + ASSERT (!str_endswith ("x", "c")); + ASSERT (str_endswith ("c", "c")); + ASSERT (str_endswith ("abc", "c")); + + ASSERT (!str_endswith ("", "xyz")); + ASSERT (!str_endswith ("x", "xyz")); + ASSERT (!str_endswith ("a", "xyz")); + ASSERT (!str_endswith ("abc", "xyz")); + ASSERT (str_endswith ("xyz", "xyz")); + ASSERT (str_endswith ("yxxyz", "xyz")); + + return test_exit_status; +} -- 2.43.0
>From b20e8f40ea47cb80ef2f6f01dd34093b4eaca23b Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 10:12:08 +0100 Subject: [PATCH 5/8] git-merge-changelog, gen-uni-tables: Use str_startswith. * lib/git-merge-changelog.c (main): Use str_startswith. * lib/gen-uni-tables.c (output_predicate, is_property_composite, is_nonspacing): Likewise. * modules/git-merge-changelog (Depends-on): Add str_startswith. * modules/gen-uni-tables (Depends-on): Likewise. --- ChangeLog | 9 +++++++++ lib/gen-uni-tables.c | 6 +++--- lib/git-merge-changelog.c | 4 ++-- modules/gen-uni-tables | 1 + modules/git-merge-changelog | 1 + 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b57ea5cae1..1355aa2361 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2025-01-03 Bruno Haible <br...@clisp.org> + + git-merge-changelog, gen-uni-tables: Use str_startswith. + * lib/git-merge-changelog.c (main): Use str_startswith. + * lib/gen-uni-tables.c (output_predicate, is_property_composite, + is_nonspacing): Likewise. + * modules/git-merge-changelog (Depends-on): Add str_startswith. + * modules/gen-uni-tables (Depends-on): Likewise. + 2025-01-03 Bruno Haible <br...@clisp.org> str_endswith: Add tests. diff --git a/lib/gen-uni-tables.c b/lib/gen-uni-tables.c index ff515854e0..c676660b07 100644 --- a/lib/gen-uni-tables.c +++ b/lib/gen-uni-tables.c @@ -776,7 +776,7 @@ output_predicate (const char *filename, bool (*predicate) (unsigned int), const fprintf (stream, "\n"); output_library_license (stream, strcmp (filename, "unictype/categ_M.h") == 0 - || strncmp (filename, "unictype/ctype_", 15) == 0 + || str_startswith (filename, "unictype/ctype_") || strcmp (filename, "uniwidth/width2.h") == 0); fprintf (stream, "\n"); @@ -3883,7 +3883,7 @@ is_property_composite (unsigned int ch) if (decomp[0] == ' ') decomp++; } - return strchr (decomp, ' ') != NULL && strncmp (decomp, "0020 ", 5) != 0; + return strchr (decomp, ' ') != NULL && str_startswith (decomp, "0020 "); } return false; } @@ -6827,7 +6827,7 @@ is_nonspacing (unsigned int ch) || is_category_Cc (ch) || (is_category_Cf (ch) && !is_property_prepended_concatenation_mark (ch)) - || strncmp (unicode_attributes[ch].name, "ZERO WIDTH ", 11) == 0 + || str_startswith (unicode_attributes[ch].name, "ZERO WIDTH ") || (ch >= 0x1160 && ch <= 0x11A7) || (ch >= 0xD7B0 && ch <= 0xD7C6) /* jungseong */ || (ch >= 0x11A8 && ch <= 0x11FF) || (ch >= 0xD7CB && ch <= 0xD7FB) /* jongseong */ ) ); diff --git a/lib/git-merge-changelog.c b/lib/git-merge-changelog.c index 74b6a5b63a..190dafc140 100644 --- a/lib/git-merge-changelog.c +++ b/lib/git-merge-changelog.c @@ -1163,9 +1163,9 @@ There is NO WARRANTY, to the extent permitted by law.\n\ printf ("GIT_REFLOG_ACTION=|%s|\n", var); #endif if (var != NULL - && ((strncmp (var, "pull", 4) == 0 + && ((str_startswith (var, "pull") && c_strstr (var, " --rebase") == NULL) - || strncmp (var, "merge origin", 12) == 0)) + || str_startswith (var, "merge origin"))) downstream = true; else { diff --git a/modules/gen-uni-tables b/modules/gen-uni-tables index c61d34194c..561a39690b 100644 --- a/modules/gen-uni-tables +++ b/modules/gen-uni-tables @@ -12,6 +12,7 @@ memcmp bool strdup strstr-simple +str_startswith configure.ac: AC_REQUIRE([AC_C_INLINE]) diff --git a/modules/git-merge-changelog b/modules/git-merge-changelog index 1ef3e1102f..9ff56dcc86 100644 --- a/modules/git-merge-changelog +++ b/modules/git-merge-changelog @@ -22,6 +22,7 @@ xalloc xmalloca fstrcmp minmax +str_startswith c-strstr fwriteerror memchr -- 2.43.0
>From e93bde59d27c491f1e6c7e3cef633d11cdd4a1d5 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 10:23:56 +0100 Subject: [PATCH 6/8] tests: Use str_startswith. * tests/test-environ.c (main): Use str_startswith. * tests/test-getprogname.c (main): Likewise. * tests/test-libtextstyle.c (main): Likewise. * tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise. * modules/environ-tests (Depends-on): Add str_startswith. * modules/getprogname-tests (Depends-on): Likewise. * modules/libtextstyle-optional-tests (Depends-on): Likewise. * modules/strsignal-tests (Depends-on): Likewise. --- ChangeLog | 10 ++++++++++ modules/environ-tests | 1 + modules/getprogname-tests | 1 + modules/libtextstyle-optional-tests | 1 + modules/strsignal-tests | 1 + tests/test-environ.c | 2 +- tests/test-getprogname.c | 2 +- tests/test-libtextstyle.c | 4 ++-- tests/test-strsignal.c | 2 +- 9 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1355aa2361..50b3f2e22e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2025-01-03 Bruno Haible <br...@clisp.org> + tests: Use str_startswith. + * tests/test-environ.c (main): Use str_startswith. + * tests/test-getprogname.c (main): Likewise. + * tests/test-libtextstyle.c (main): Likewise. + * tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise. + * modules/environ-tests (Depends-on): Add str_startswith. + * modules/getprogname-tests (Depends-on): Likewise. + * modules/libtextstyle-optional-tests (Depends-on): Likewise. + * modules/strsignal-tests (Depends-on): Likewise. + git-merge-changelog, gen-uni-tables: Use str_startswith. * lib/git-merge-changelog.c (main): Use str_startswith. * lib/gen-uni-tables.c (output_predicate, is_property_composite, diff --git a/modules/environ-tests b/modules/environ-tests index c4fe0fd11f..056096baa5 100644 --- a/modules/environ-tests +++ b/modules/environ-tests @@ -2,6 +2,7 @@ Files: tests/test-environ.c Depends-on: +str_startswith configure.ac: diff --git a/modules/getprogname-tests b/modules/getprogname-tests index bd7137f8ea..1b1bc0a53a 100644 --- a/modules/getprogname-tests +++ b/modules/getprogname-tests @@ -3,6 +3,7 @@ tests/test-getprogname.c Depends-on: string-h +str_startswith configure.ac: diff --git a/modules/libtextstyle-optional-tests b/modules/libtextstyle-optional-tests index e930a00fbe..e4dbd5d220 100644 --- a/modules/libtextstyle-optional-tests +++ b/modules/libtextstyle-optional-tests @@ -5,6 +5,7 @@ tests/test-libtextstyle-default.css Depends-on: c99 isatty +str_startswith configure.ac: gl_LIBTEXTSTYLE_OPTIONAL diff --git a/modules/strsignal-tests b/modules/strsignal-tests index ab67eb1b69..531451c4cd 100644 --- a/modules/strsignal-tests +++ b/modules/strsignal-tests @@ -4,6 +4,7 @@ tests/signature.h tests/macros.h Depends-on: +str_startswith configure.ac: diff --git a/tests/test-environ.c b/tests/test-environ.c index a5c74ced79..21641b894c 100644 --- a/tests/test-environ.c +++ b/tests/test-environ.c @@ -35,7 +35,7 @@ main () for (; (string = *remaining_variables) != NULL; remaining_variables++) { - if (strncmp (string, "PATH=", 5) == 0) + if (str_startswith (string, "PATH=")) /* Found the PATH environment variable. */ return 0; } diff --git a/tests/test-getprogname.c b/tests/test-getprogname.c index 088561cf30..e1e8cb5350 100644 --- a/tests/test-getprogname.c +++ b/tests/test-getprogname.c @@ -36,7 +36,7 @@ main (void) with "lt-" (depends on the platform). But the name of the temporary executable is a detail that should not be visible to the end user and to the test suite. Remove this "lt-" prefix here. */ - if (strncmp (p, "lt-", 3) == 0) + if (str_startswith (p, "lt-")) p += 3; /* Note: You can make this test fail diff --git a/tests/test-libtextstyle.c b/tests/test-libtextstyle.c index e992daf1f2..6545a00223 100644 --- a/tests/test-libtextstyle.c +++ b/tests/test-libtextstyle.c @@ -34,9 +34,9 @@ main (int argc, char *argv[]) for (i = 1; i < argc; i++) { const char *arg = argv[i]; - if (strncmp (arg, "--color=", 8) == 0) + if (str_startswith (arg, "--color=")) handle_color_option (arg + 8); - else if (strncmp (arg, "--style=", 8) == 0) + else if (str_startswith (arg, "--style=")) handle_style_option (arg + 8); else if (arg[0] == '-') { diff --git a/tests/test-strsignal.c b/tests/test-strsignal.c index 6c44203734..4ed4cc3e23 100644 --- a/tests/test-strsignal.c +++ b/tests/test-strsignal.c @@ -33,7 +33,7 @@ SIGNATURE_CHECK (strsignal, char *, (int)); /* In this case, we can guarantee some signal descriptions. But allow the actual result to be longer than the expected result. */ # define ASSERT_DESCRIPTION(actual, expected) \ - ASSERT (strncmp (actual, expected, strlen (expected)) == 0) + ASSERT (str_startswith (actual, expected)) #endif int -- 2.43.0
>From 26a37f80ead11e2e69dddf8d66aa34e0432a145e Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 10:38:58 +0100 Subject: [PATCH 7/8] gen-uni-tables, get-rusage-data, isatty: Use str_endswith. * lib/gen-uni-tables.c (fill_attributes): Use str_endswith. * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise. * lib/isatty.c (IsCygwinConsoleHandle): Likewise. * modules/gen-uni-tables (Depends-on): Add str_endswith. * modules/get-rusage-data (Depends-on): Likewise. * modules/isatty (Depends-on): Likewise. --- ChangeLog | 10 ++++++++++ lib/gen-uni-tables.c | 4 ++-- lib/get-rusage-data.c | 5 ++--- lib/isatty.c | 3 +-- modules/gen-uni-tables | 1 + modules/get-rusage-data | 1 + modules/isatty | 1 + 7 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50b3f2e22e..b6a71b15e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-01-03 Bruno Haible <br...@clisp.org> + + gen-uni-tables, get-rusage-data, isatty: Use str_endswith. + * lib/gen-uni-tables.c (fill_attributes): Use str_endswith. + * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise. + * lib/isatty.c (IsCygwinConsoleHandle): Likewise. + * modules/gen-uni-tables (Depends-on): Add str_endswith. + * modules/get-rusage-data (Depends-on): Likewise. + * modules/isatty (Depends-on): Likewise. + 2025-01-03 Bruno Haible <br...@clisp.org> tests: Use str_startswith. diff --git a/lib/gen-uni-tables.c b/lib/gen-uni-tables.c index c676660b07..2bac68c2da 100644 --- a/lib/gen-uni-tables.c +++ b/lib/gen-uni-tables.c @@ -219,7 +219,7 @@ fill_attributes (const char *unicodedata_filename) i = strtoul (field0, NULL, 16); if (field1[0] == '<' && strlen (field1) >= 9 - && strcmp (field1 + strlen (field1) - 8, ", First>") == 0) + && str_endswith (field1, ", First>")) { /* Deal with a range. */ lineno++; @@ -246,7 +246,7 @@ fill_attributes (const char *unicodedata_filename) } if (!(field1[0] == '<' && strlen (field1) >= 8 - && strcmp (field1 + strlen (field1) - 7, ", Last>") == 0)) + && str_endswith (field1, ", Last>"))) { fprintf (stderr, "missing end range in '%s':%d\n", unicodedata_filename, lineno); diff --git a/lib/get-rusage-data.c b/lib/get-rusage-data.c index b4df73f766..0fafc75a20 100644 --- a/lib/get-rusage-data.c +++ b/lib/get-rusage-data.c @@ -174,9 +174,8 @@ get_rusage_data_via_setrlimit (void) struct utsname buf; if (uname (&buf) == 0 - && strlen (buf.release) >= 5 - && (strcmp (buf.release + strlen (buf.release) - 5, "11.00") == 0 - || strcmp (buf.release + strlen (buf.release) - 5, "11.11") == 0)) + && (str_endswith (buf.release, "11.00") + || str_endswith (buf.release, "11.11"))) return 0; } # endif diff --git a/lib/isatty.c b/lib/isatty.c index 69371af607..23e3ab8f6d 100644 --- a/lib/isatty.c +++ b/lib/isatty.c @@ -130,8 +130,7 @@ static BOOL IsCygwinConsoleHandle (HANDLE h) or higher. */ if (QueryFullProcessImageNameFunc (processHandle, 0, buf, &bufsize)) { - if (strlen (buf) >= 11 - && strcmp (buf + strlen (buf) - 11, "\\mintty.exe") == 0) + if (str_endswith (buf, "\\mintty.exe")) result = TRUE; } CloseHandle (processHandle); diff --git a/modules/gen-uni-tables b/modules/gen-uni-tables index 561a39690b..5808aef3ad 100644 --- a/modules/gen-uni-tables +++ b/modules/gen-uni-tables @@ -13,6 +13,7 @@ bool strdup strstr-simple str_startswith +str_endswith configure.ac: AC_REQUIRE([AC_C_INLINE]) diff --git a/modules/get-rusage-data b/modules/get-rusage-data index 1a7bf89903..8d9110ac16 100644 --- a/modules/get-rusage-data +++ b/modules/get-rusage-data @@ -12,6 +12,7 @@ unistd-h extensions getpagesize vma-iter +str_endswith configure.ac: AC_CHECK_FUNCS_ONCE([sbrk setrlimit]) diff --git a/modules/isatty b/modules/isatty index e2fd7f09cd..7499b53933 100644 --- a/modules/isatty +++ b/modules/isatty @@ -9,6 +9,7 @@ Depends-on: unistd-h msvc-inval [test $REPLACE_ISATTY = 1] msvc-nothrow [test $REPLACE_ISATTY = 1] +str_endswith [test $REPLACE_ISATTY = 1] configure.ac: gl_FUNC_ISATTY -- 2.43.0
>From f2b0e184b5ac0182b545fad57ea7bec2cb4b621d Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 3 Jan 2025 10:43:15 +0100 Subject: [PATCH 8/8] tests: Use str_endswith. * tests/test-canonicalize.c (main): Use str_endswith. * tests/test-canonicalize-lgpl.c (main): Likewise. * tests/test-setlocale-w32utf8.c (main): Likewise. * modules/canonicalize-tests (Depends-on): Add str_endswith. * modules/canonicalize-lgpl-tests (Depends-on): Likewise. * modules/setlocale-tests (Depends-on): Likewise. --- ChangeLog | 8 ++++++++ modules/canonicalize-lgpl-tests | 1 + modules/canonicalize-tests | 1 + modules/setlocale-tests | 1 + tests/test-canonicalize-lgpl.c | 6 ++---- tests/test-canonicalize.c | 17 ++++++----------- tests/test-setlocale-w32utf8.c | 2 +- 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6a71b15e2..300538b682 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2025-01-03 Bruno Haible <br...@clisp.org> + tests: Use str_endswith. + * tests/test-canonicalize.c (main): Use str_endswith. + * tests/test-canonicalize-lgpl.c (main): Likewise. + * tests/test-setlocale-w32utf8.c (main): Likewise. + * modules/canonicalize-tests (Depends-on): Add str_endswith. + * modules/canonicalize-lgpl-tests (Depends-on): Likewise. + * modules/setlocale-tests (Depends-on): Likewise. + gen-uni-tables, get-rusage-data, isatty: Use str_endswith. * lib/gen-uni-tables.c (fill_attributes): Use str_endswith. * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise. diff --git a/modules/canonicalize-lgpl-tests b/modules/canonicalize-lgpl-tests index 73a0e32abb..d2b864842a 100644 --- a/modules/canonicalize-lgpl-tests +++ b/modules/canonicalize-lgpl-tests @@ -8,6 +8,7 @@ Depends-on: ignore-value same-inode symlink +str_endswith configure.ac: diff --git a/modules/canonicalize-tests b/modules/canonicalize-tests index e043a8daca..5984f665bb 100644 --- a/modules/canonicalize-tests +++ b/modules/canonicalize-tests @@ -7,6 +7,7 @@ Depends-on: ignore-value same-inode symlink +str_endswith configure.ac: diff --git a/modules/setlocale-tests b/modules/setlocale-tests index 23cc6ddd17..bd85353d61 100644 --- a/modules/setlocale-tests +++ b/modules/setlocale-tests @@ -18,6 +18,7 @@ m4/windows-rc.m4 Depends-on: strdup +str_endswith test-xfail configure.ac: diff --git a/tests/test-canonicalize-lgpl.c b/tests/test-canonicalize-lgpl.c index 2a4f5e2ecd..5450bb9b14 100644 --- a/tests/test-canonicalize-lgpl.c +++ b/tests/test-canonicalize-lgpl.c @@ -178,8 +178,7 @@ main (void) ASSERT (result1 != NULL); ASSERT (result2 != NULL); ASSERT (strcmp (result1, result2) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/tra"), - "/" BASE "/tra") == 0); + ASSERT (str_endswith (result1, "/" BASE "/tra")); free (result1); free (result2); } @@ -194,8 +193,7 @@ main (void) ASSERT (result3 != NULL); ASSERT (strcmp (result1, result2) == 0); ASSERT (strcmp (result2, result3) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/lum"), - "/" BASE "/lum") == 0); + ASSERT (str_endswith (result1, "/" BASE "/lum")); free (result1); free (result2); free (result3); diff --git a/tests/test-canonicalize.c b/tests/test-canonicalize.c index 0f69f98714..083bf1703a 100644 --- a/tests/test-canonicalize.c +++ b/tests/test-canonicalize.c @@ -204,8 +204,7 @@ main (void) { char *result1 = canonicalize_filename_mode (BASE "/huk", CAN_NOLINKS); ASSERT (result1 != NULL); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/huk"), - "/" BASE "/huk") == 0); + ASSERT (str_endswith (result1, "/" BASE "/huk")); free (result1); } @@ -219,8 +218,7 @@ main (void) ASSERT (result3 != NULL); ASSERT (strcmp (result1, result2) == 0); ASSERT (strcmp (result2, result3) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/tra"), - "/" BASE "/tra") == 0); + ASSERT (str_endswith (result1, "/" BASE "/tra")); free (result1); free (result2); free (result3); @@ -239,8 +237,7 @@ main (void) ASSERT (strcmp (result1, result2) == 0); ASSERT (strcmp (result2, result3) == 0); ASSERT (strcmp (result3, result4) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/lum"), - "/" BASE "/lum") == 0); + ASSERT (str_endswith (result1, "/" BASE "/lum")); free (result1); free (result2); free (result3); @@ -330,8 +327,7 @@ main (void) ASSERT (strcmp (result1, result2) == 0); ASSERT (strcmp (result2, result3) == 0); ASSERT (strcmp (result3, result4) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/zzz"), - "/" BASE "/zzz") == 0); + ASSERT (str_endswith (result1, "/" BASE "/zzz")); free (result1); free (result2); free (result3); @@ -351,8 +347,7 @@ main (void) ASSERT (strcmp (result1, result2) == 0); ASSERT (strcmp (result2, result3) == 0); ASSERT (strcmp (result3, result4) == 0); - ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/wum"), - "/" BASE "/wum") == 0); + ASSERT (str_endswith (result1, "/" BASE "/wum")); free (result1); free (result2); free (result3); @@ -365,7 +360,7 @@ main (void) char *result2 = canonicalize_filename_mode ("t-can.zzz/zzz", CAN_MISSING); ASSERT (result1 == NULL); ASSERT (result2 != NULL); - ASSERT (strcmp (result2 + strlen (result2) - 14, "/t-can.zzz/zzz") == 0); + ASSERT (str_endswith (result2, "/t-can.zzz/zzz")); free (result2); } diff --git a/tests/test-setlocale-w32utf8.c b/tests/test-setlocale-w32utf8.c index 92156c7c01..51828db18e 100644 --- a/tests/test-setlocale-w32utf8.c +++ b/tests/test-setlocale-w32utf8.c @@ -41,7 +41,7 @@ main (void) /* With the legacy system settings, expect some mixed locale, due to the limitations of the native setlocale(). With the modern system settings, expect some "ll_CC.UTF-8" name. */ - if (!((strlen (name) > 6 && strcmp (name + strlen (name) - 6, ".UTF-8") == 0) + if (!((strlen (name) > 6 && str_endswith (name, ".UTF-8")) || strcmp (name, "LC_COLLATE=English_United States.65001;" "LC_CTYPE=English_United States.65001;" "LC_MONETARY=English_United States.65001;" -- 2.43.0