On Tue, Jul 01, 2014 at 10:45:19AM -0700, Junio C Hamano wrote:

> Jeff King <p...@peff.net> writes:
> > When we are running a string-list foreach or filter, the
> > callback function sees only the string_list_item, along with
> > a void* data pointer provided by the caller. This is
> > sufficient for most purposes.
> >
> > However, it can also be useful to know the position of the
> > item within the string (for example, if the data pointer
> s/the string/&-list/ (or s/&/&_list/).

Thanks, yeah.

> While I can buy that some callers would want to learn the pos in the
> list, I am not sure if this is a good direction to go.  Primarily, I
> am having trouble sifting between "want" and "need".
> How often do callers want to do this?  If only narrow specialized
> callers want this, is it unreasonable to ask them to add a "int ctr"
> in their cb_data and use "pos = ((struct theirs *)cb_data)->ctr++"
> in their callback instead?

Not all that often, I suppose (I only add one caller in this series). I
just found it a little hack-ish to force callers to keep their own
counter when we already have it (especially because it is not too hard
to get it wrong, for example by forgetting to increment the counter in
one code path of the callback).

Here's what the caller would look like without "pos" (done as a patch on
top of the series, so pos is still there, but no longer used).

diff --git a/builtin/tag.c b/builtin/tag.c
index f17192c..dc6f105 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -151,14 +151,20 @@ static int util_is_not_null(struct string_list_item *it, 
int pos, void *data)
        return !!it->util;
-static int matches_contains(struct string_list_item *it, int pos, void *data)
+struct contains_callback_data {
+       int ctr;
+       unsigned char *contains;
+static int matches_contains(struct string_list_item *it, int pos, void *vdata)
-       unsigned char *contains = data;
-       return contains[pos];
+       struct contains_callback_data *data = vdata;
+       return data->contains[data->ctr++];
 static void limit_by_contains(struct string_list *tags, struct commit_list 
+       struct contains_callback_data cbdata;
        struct commit_list *tag_commits = NULL, **tail = &tag_commits;
        unsigned char *result;
        int i;
@@ -180,7 +186,10 @@ static void limit_by_contains(struct string_list *tags, 
struct commit_list *with
        result = xmalloc(tags->nr);
        commit_contains(with, tag_commits, NULL, result);
-       filter_string_list(tags, 1, matches_contains, result);
+       cbdata.ctr = 0;
+       cbdata.contains = result;
+       filter_string_list(tags, 1, matches_contains, &cbdata);

So I think it's a small change in a lot of places rather than a kind of
ugly change in one spot.

All that being said, I think the real issue here is that I want more
than a string list (I am already using the util field for the sha1, but
this code would be potentially simpler if I could also store the commit
object). In the long run I hope to factor out a ref-listing API that can
be used by tag, branch, and for-each-ref. And then this string-list code
would go away in favor of a more expansive struct. So it may not be
worth worrying about keeping it too clean.

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to