From: shejialuo <shejialuo@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
Patrick Steinhardt <ps@pks.im>, Jeff King <peff@peff.net>
Subject: [PATCH v3 0/8] enhance "string_list" code and test
Date: Sun, 29 Jun 2025 12:26:15 +0800 [thread overview]
Message-ID: <aGDAZ6a0-PyXXGmK@ArchLinux> (raw)
In-Reply-To: <aCoDB9P5XV1lHMil@ArchLinux>
Hi All:
I finally finish the version 2. And I don't provide the range-diff due
to that I add more commits compared with version 1.
This patch could be organized into three parts:
1. [PATCH v2 1/8]
Fix simple sign warnings of the loop iterator.
2. [PATCH v2 2/8] - [PATCH v2 4/8]
Remove unncessary code, improve the logic and finally enable sign
compare warnings check.
3. [PATCH v2 5/8] - [PATCH v2 8/8]
Remove test to the unit test.
---
Changes since v2:
1. [PATCH v3 1/8]: improve the commit message to explain that we would
handle a warning in the later commits.
2. [PATCH v3 2/8] and [PATCH v2 3/8]: improve the commit message to add
the history background.
3. [PATCH v3 4/8]: improve the commit message to show why the current
bianry search algorithm introduces the sign warning and how to change
it to fix the sign warning.
4. [PATCH v3 5/8] - [PATCH v3 8/8]: remove list into test helper instead
of test itself for reducing the shared state.
5. [PATCH v3 8/8]: improve the commit message to say why we can't delete
"test-tool string_list" totally.
Thanks,
Jialuo
shejialuo (8):
string-list: fix sign compare warnings for loop iterator
string-list: remove unused "insert_at" parameter from add_entry
string-list: return index directly when inserting an existing element
string-list: enable sign compare warnings check
u-string-list: move "test_split" into "u-string-list.c"
u-string-list: move "test_split_in_place" to "u-string-list.c"
u-string-list: move "filter string" test to "u-string-list.c"
u-string-list: move "remove duplicates" test to "u-string-list.c"
Makefile | 1 +
string-list.c | 48 +++-----
t/helper/test-string-list.c | 96 ---------------
t/meson.build | 2 +-
t/t0063-string-list.sh | 142 ----------------------
t/unit-tests/u-string-list.c | 227 +++++++++++++++++++++++++++++++++++
6 files changed, 249 insertions(+), 267 deletions(-)
delete mode 100755 t/t0063-string-list.sh
create mode 100644 t/unit-tests/u-string-list.c
Range-diff against v2:
1: 4fb4546525 ! 1: a69eb0f7b8 string-list: fix sign compare warnings for loop iterator
@@ Metadata
## Commit message ##
string-list: fix sign compare warnings for loop iterator
- In "string-list.c", there are six warnings which are emitted by
- "Wsign-compare". And five warnings are caused by the loop iterator type
- mismatch. Let's fix these five warnings by changing the `int` type to
- `size_t` type of the loop iterator.
+ There are a couple of "-Wsign-compare" warnings in "string-list.c". Fix
+ trivial ones that result from a mismatched loop iterator type.
+
+ There is a single warning left after these fixes. This warning needs
+ a bit more care and is thus handled in subsequent commits.
Signed-off-by: shejialuo <shejialuo@gmail.com>
2: 3721c92803 ! 2: 35550b3b7d string-list: remove unused "insert_at" parameter from add_entry
@@ Commit message
However, we only use "add_entry" in "string_list_insert" function and we
always pass the "-1" for "insert_at" parameter. So, we never use this
- parameter to insert element in a user specified position. Let's delete
- this parameter. If there is any requirement later, we need to use a
- better way to do this.
+ parameter to insert element in a user specified position.
+
+ And we should know why there is such code path in the first place. We
+ used to have another function "string_list_insert_at_index()", which
+ uses the extra "insert_at" parameter. And in f8c4ab611a (string_list:
+ remove string_list_insert_at_index() from its API, 2014-11-24), we
+ remove this function but we don't clean all the code path.
+
+ Let's simply delete this parameter as we'd better use "strmap" for such
+ functionality.
Signed-off-by: shejialuo <shejialuo@gmail.com>
3: fa1d22c93d ! 3: 7877b528e4 string-list: return index directly when inserting an existing element
@@ Commit message
When inserting an existing element, "add_entry" would convert "index"
value to "-1-index" to indicate the caller that this element is in the
- list already.
+ list already. However, in "string_list_insert", we would simply convert
+ this to the original positive index without any further action.
- However, in "string_list_insert", we would simply convert this to the
- original positive index without any further action. Let's directly
- return the index as we don't care about whether the element is in the
- list by using "add_entry".
+ In 8fd2cb4069 (Extract helper bits from c-merge-recursive work,
+ 2006-07-25), we create "path-list.c" and then introduce above code path.
- In the future, if we want to let "add_entry" tell the caller, we may add
- "int *exact_match" parameter to "add_entry" instead of converting the
- index to negative to indicate.
+ Let's directly return the index as we don't care about whether the
+ element is in the list by using "add_entry". In the future, if we want
+ to let "add_entry" tell the caller, we may add "int *exact_match"
+ parameter to "add_entry" instead of converting the index to negative to
+ indicate.
Signed-off-by: shejialuo <shejialuo@gmail.com>
4: 02e5c4307b ! 4: 50c4dbff5c string-list: enable sign compare warnings check
@@ Metadata
## Commit message ##
string-list: enable sign compare warnings check
- The only sign compare warning in "string-list" is that we compare the
- `index` of the `int` type with the `list->nr` of unsigned type. We get
- index by calling "get_entry_index", which would always return unsigned
- index.
+ In "add_entry", we call "get_entry_index" function to get the inserted
+ position. However, as the return type of "get_entry_index" function is
+ `int`, there is a sign compare warning when comparing the `index` with
+ the `list-nr` of unsigned type.
- Let's change the return type of "get_entry_index" to be "size_t" by
- slightly modifying the binary search algorithm. Instead of letting
- "left" to be "-1" initially, assign 0 to it.
+ "get_entry_index" would always return unsigned index. However, the
+ current binary search algorithm initializes "left" to be "-1", which
+ necessitates the use of signed `int` return type.
+
+ The reason why we need to assign "left" to be "-1" is that in the
+ `while` loop, we increment "left" by 1 to determine whether the loop
+ should end. This design choice, while functional, forces us to use
+ signed arithmetic throughout the function.
+
+ To resolve this sign comparison issue, let's modify the binary search
+ algorithm with the following approach:
+
+ 1. Initialize "left" to 0 instead of -1
+ 2. Use `left < right` as the loop termination condition instead of
+ `left + 1 < right`
+ 3. When searching the right part, set `left = middle + 1` instead of
+ `middle`
Then, we could delete "#define DISABLE_SIGN_COMPARE_WARNING" to enable
- sign warnings check for "string-list"
+ sign warnings check for "string-list".
Signed-off-by: shejialuo <shejialuo@gmail.com>
5: 990ce4db0f ! 5: ab2aec5887 u-string-list: move "test_split" into "u-string-list.c"
@@ t/unit-tests/u-string-list.c (new)
+ string_list_append(list, arg);
+}
+
-+static void t_string_list_clear(struct string_list *list, int free_util)
-+{
-+ string_list_clear(list, free_util);
-+ cl_assert_equal_p(list->items, NULL);
-+ cl_assert_equal_i(list->nr, 0);
-+ cl_assert_equal_i(list->alloc, 0);
-+}
-+
+static void t_string_list_equal(struct string_list *list,
+ struct string_list *expected_strings)
+{
@@ t/unit-tests/u-string-list.c (new)
+ expected_strings->items[i].string);
+}
+
-+static void t_string_list_split(struct string_list *list, const char *data,
-+ int delim, int maxsplit, ...)
++static void t_string_list_split(const char *data, int delim, int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
++ struct string_list list = STRING_LIST_INIT_DUP;
+ va_list ap;
+ int len;
+
@@ t/unit-tests/u-string-list.c (new)
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
-+ string_list_clear(list, 0);
-+ len = string_list_split(list, data, delim, maxsplit);
++ string_list_clear(&list, 0);
++ len = string_list_split(&list, data, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
-+ t_string_list_equal(list, &expected_strings);
++ t_string_list_equal(&list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
++ string_list_clear(&list, 0);
+}
+
+void test_string_list__split(void)
+{
-+ struct string_list list = STRING_LIST_INIT_DUP;
-+
-+ t_string_list_split(&list, "foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL);
-+ t_string_list_split(&list, "foo:bar:baz", ':', 0, "foo:bar:baz", NULL);
-+ t_string_list_split(&list, "foo:bar:baz", ':', 1, "foo", "bar:baz", NULL);
-+ t_string_list_split(&list, "foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL);
-+ t_string_list_split(&list, "foo:bar:", ':', -1, "foo", "bar", "", NULL);
-+ t_string_list_split(&list, "", ':', -1, "", NULL);
-+ t_string_list_split(&list, ":", ':', -1, "", "", NULL);
-+
-+ t_string_list_clear(&list, 0);
++ t_string_list_split("foo:bar:baz", ':', -1, "foo", "bar", "baz", NULL);
++ t_string_list_split("foo:bar:baz", ':', 0, "foo:bar:baz", NULL);
++ t_string_list_split("foo:bar:baz", ':', 1, "foo", "bar:baz", NULL);
++ t_string_list_split("foo:bar:baz", ':', 2, "foo", "bar", "baz", NULL);
++ t_string_list_split("foo:bar:", ':', -1, "foo", "bar", "", NULL);
++ t_string_list_split("", ':', -1, "", NULL);
++ t_string_list_split(":", ':', -1, "", "", NULL);
+}
6: 5a02f590df ! 6: 06aca89b57 u-string-list: move "test_split_in_place" to "u-string-list.c"
@@ t/t0063-string-list.sh: test_description='Test string list functionality'
## t/unit-tests/u-string-list.c ##
@@ t/unit-tests/u-string-list.c: void test_string_list__split(void)
-
- t_string_list_clear(&list, 0);
+ t_string_list_split("", ':', -1, "", NULL);
+ t_string_list_split(":", ':', -1, "", "", NULL);
}
+
-+static void t_string_list_split_in_place(struct string_list *list, const char *data,
-+ const char *delim, int maxsplit, ...)
++static void t_string_list_split_in_place(const char *data, const char *delim,
++ int maxsplit, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
++ struct string_list list = STRING_LIST_INIT_NODUP;
+ char *string = xstrdup(data);
+ va_list ap;
+ int len;
@@ t/unit-tests/u-string-list.c: void test_string_list__split(void)
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
-+ string_list_clear(list, 0);
-+ len = string_list_split_in_place(list, string, delim, maxsplit);
++ string_list_clear(&list, 0);
++ len = string_list_split_in_place(&list, string, delim, maxsplit);
+ cl_assert_equal_i(len, expected_strings.nr);
-+ t_string_list_equal(list, &expected_strings);
++ t_string_list_equal(&list, &expected_strings);
+
+ free(string);
+ string_list_clear(&expected_strings, 0);
++ string_list_clear(&list, 0);
+}
+
+void test_string_list__split_in_place(void)
+{
-+ struct string_list list = STRING_LIST_INIT_NODUP;
-+
-+ t_string_list_split_in_place(&list, "foo:;:bar:;:baz:;:", ":;", -1,
++ t_string_list_split_in_place("foo:;:bar:;:baz:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "baz", "", "", "", NULL);
-+ t_string_list_split_in_place(&list, "foo:;:bar:;:baz", ":;", 0,
++ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 0,
+ "foo:;:bar:;:baz", NULL);
-+ t_string_list_split_in_place(&list, "foo:;:bar:;:baz", ":;", 1,
++ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 1,
+ "foo", ";:bar:;:baz", NULL);
-+ t_string_list_split_in_place(&list, "foo:;:bar:;:baz", ":;", 2,
++ t_string_list_split_in_place("foo:;:bar:;:baz", ":;", 2,
+ "foo", "", ":bar:;:baz", NULL);
-+ t_string_list_split_in_place(&list, "foo:;:bar:;:", ":;", -1,
++ t_string_list_split_in_place("foo:;:bar:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "", NULL);
-+
-+ t_string_list_clear(&list, 0);
+}
7: 87a6ec722d ! 7: 4cc76a6fb4 u-string-list: move "filter string" test to "u-string-list.c"
@@ t/unit-tests/u-string-list.c: static void t_vcreate_string_list_dup(struct strin
+ va_end(ap);
+}
+
- static void t_string_list_clear(struct string_list *list, int free_util)
++static void t_string_list_clear(struct string_list *list, int free_util)
++{
++ string_list_clear(list, free_util);
++ cl_assert_equal_p(list->items, NULL);
++ cl_assert_equal_i(list->nr, 0);
++ cl_assert_equal_i(list->alloc, 0);
++}
++
+ static void t_string_list_equal(struct string_list *list,
+ struct string_list *expected_strings)
{
- string_list_clear(list, free_util);
@@ t/unit-tests/u-string-list.c: void test_string_list__split_in_place(void)
-
- t_string_list_clear(&list, 0);
+ t_string_list_split_in_place("foo:;:bar:;:", ":;", -1,
+ "foo", "", "", "bar", "", "", "", NULL);
}
+
+static int prefix_cb(struct string_list_item *item, void *cb_data)
@@ t/unit-tests/u-string-list.c: void test_string_list__split_in_place(void)
+ return starts_with(item->string, prefix);
+}
+
-+static void t_string_list_filter(struct string_list *list,
-+ string_list_each_func_t want, void *cb_data, ...)
++static void t_string_list_filter(struct string_list *list, ...)
+{
+ struct string_list expected_strings = STRING_LIST_INIT_DUP;
++ const char *prefix = "y";
+ va_list ap;
+
-+ va_start(ap, cb_data);
++ va_start(ap, list);
+ t_vcreate_string_list_dup(&expected_strings, 0, ap);
+ va_end(ap);
+
-+ filter_string_list(list, 0, want, cb_data);
++ filter_string_list(list, 0, prefix_cb, (void *)prefix);
+ t_string_list_equal(list, &expected_strings);
+
+ string_list_clear(&expected_strings, 0);
@@ t/unit-tests/u-string-list.c: void test_string_list__split_in_place(void)
+void test_string_list__filter(void)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
-+ const char *prefix = "y";
+
+ t_create_string_list_dup(&list, 0, NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, NULL);
++ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "no", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, NULL);
++ t_string_list_filter(&list, NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, "yes", NULL);
++ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "no", "yes", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, "yes", NULL);
++ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "yes", "no", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, "yes", NULL);
++ t_string_list_filter(&list, "yes", NULL);
+
+ t_create_string_list_dup(&list, 0, "y1", "y2", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, "y1", "y2", NULL);
++ t_string_list_filter(&list, "y1", "y2", NULL);
+
+ t_create_string_list_dup(&list, 0, "y2", "y1", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, "y2", "y1", NULL);
++ t_string_list_filter(&list, "y2", "y1", NULL);
+
+ t_create_string_list_dup(&list, 0, "x1", "x2", NULL);
-+ t_string_list_filter(&list, prefix_cb, (void*)prefix, NULL);
++ t_string_list_filter(&list, NULL);
+
+ t_string_list_clear(&list, 0);
+}
8: 55269e7fcb ! 8: b608047d40 u-string-list: move "remove duplicates" test to "u-string-list.c"
@@ Commit message
Also we could simply remove "DISABLE_SIGN_COMPARE_WARNINGS" due to we
have already deleted related code.
+ Unfortunately, we cannot totally remove "test-string-list.c" due to that
+ we would test the performance of sorting about string list by executing
+ "test-tool string-list sort" in "p0071-sort.sh".
+
Signed-off-by: shejialuo <shejialuo@gmail.com>
## t/helper/test-string-list.c ##
--
2.50.0
next prev parent reply other threads:[~2025-06-29 4:26 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-22 14:53 [PATCH 0/5] enhance "string_list" code and test shejialuo
2025-04-22 14:54 ` [PATCH 1/5] string-list: fix sign compare warnings shejialuo
2025-04-22 21:02 ` Junio C Hamano
2025-04-24 12:27 ` shejialuo
2025-04-22 14:54 ` [PATCH 2/5] u-string-list: move "test_split" into "u-string-list.c" shejialuo
2025-04-22 21:27 ` Junio C Hamano
2025-04-24 12:50 ` shejialuo
2025-04-23 11:52 ` Patrick Steinhardt
2025-04-24 12:53 ` shejialuo
2025-04-22 14:55 ` [PATCH 3/5] u-string-list: move "test_split_in_place" to "u-string-list.c" shejialuo
2025-04-23 11:53 ` Patrick Steinhardt
2025-04-22 14:55 ` [PATCH 4/5] u-string-list: move "filter string" test " shejialuo
2025-04-22 14:55 ` [PATCH 5/5] u-string-list: move "remove duplicates" " shejialuo
2025-04-23 11:53 ` Patrick Steinhardt
2025-04-24 12:56 ` shejialuo
2025-05-18 15:55 ` [PATCH v2 0/8] enhance "string_list" code and test shejialuo
2025-05-18 15:56 ` [PATCH v2 1/8] string-list: fix sign compare warnings for loop iterator shejialuo
2025-05-19 7:17 ` Patrick Steinhardt
2025-05-26 13:50 ` shejialuo
2025-05-18 15:57 ` [PATCH v2 2/8] string-list: remove unused "insert_at" parameter from add_entry shejialuo
2025-05-19 7:17 ` Patrick Steinhardt
2025-05-26 13:52 ` shejialuo
2025-05-19 7:51 ` Jeff King
2025-05-26 14:01 ` shejialuo
2025-05-26 14:21 ` Patrick Steinhardt
2025-05-18 15:57 ` [PATCH v2 3/8] string-list: return index directly when inserting an existing element shejialuo
2025-05-19 7:18 ` Patrick Steinhardt
2025-05-26 14:13 ` shejialuo
2025-05-19 7:58 ` Jeff King
2025-05-26 14:20 ` shejialuo
2025-05-18 15:57 ` [PATCH v2 4/8] string-list: enable sign compare warnings check shejialuo
2025-05-19 7:18 ` Patrick Steinhardt
2025-05-26 14:27 ` shejialuo
2025-05-18 15:57 ` [PATCH v2 5/8] u-string-list: move "test_split" into "u-string-list.c" shejialuo
2025-05-19 7:17 ` Patrick Steinhardt
2025-05-18 15:57 ` [PATCH v2 6/8] u-string-list: move "test_split_in_place" to "u-string-list.c" shejialuo
2025-05-18 15:58 ` [PATCH v2 7/8] u-string-list: move "filter string" test " shejialuo
2025-05-19 7:18 ` Patrick Steinhardt
2025-05-26 14:33 ` shejialuo
2025-05-18 15:58 ` [PATCH v2 8/8] u-string-list: move "remove duplicates" " shejialuo
2025-05-19 7:18 ` Patrick Steinhardt
2025-06-29 4:26 ` shejialuo [this message]
2025-06-29 4:27 ` [PATCH v3 1/8] string-list: fix sign compare warnings for loop iterator shejialuo
2025-06-29 4:27 ` [PATCH v3 2/8] string-list: remove unused "insert_at" parameter from add_entry shejialuo
2025-06-29 4:27 ` [PATCH v3 3/8] string-list: return index directly when inserting an existing element shejialuo
2025-06-29 4:28 ` [PATCH v3 4/8] string-list: enable sign compare warnings check shejialuo
2025-06-29 4:28 ` [PATCH v3 5/8] u-string-list: move "test_split" into "u-string-list.c" shejialuo
2025-06-29 4:28 ` [PATCH v3 6/8] u-string-list: move "test_split_in_place" to "u-string-list.c" shejialuo
2025-06-29 4:28 ` [PATCH v3 7/8] u-string-list: move "filter string" test " shejialuo
2025-06-29 4:28 ` [PATCH v3 8/8] u-string-list: move "remove duplicates" " shejialuo
2025-07-04 5:24 ` [PATCH v3 0/8] enhance "string_list" code and test Patrick Steinhardt
2025-07-07 15:10 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aGDAZ6a0-PyXXGmK@ArchLinux \
--to=shejialuo@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=peff@peff.net \
--cc=ps@pks.im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).