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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+
+ 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 <[email protected]>
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 <[email protected]>, 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 <[email protected]>
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 <[email protected]>
+ 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 <[email protected]>
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 <[email protected]>
+
+ 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 <[email protected]>
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 <[email protected]>, 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 <[email protected]>
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 <[email protected]>
+ 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 <[email protected]>
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 <[email protected]>
+
+ 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+ 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 <[email protected]>
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 <[email protected]>
+
+ 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+ 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