After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 548666 - [PATCH] Allow searching for a given item in a GSequence
[PATCH] Allow searching for a given item in a GSequence
Status: RESOLVED INVALID
Product: glib
Classification: Platform
Component: general
2.17.x
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2008-08-20 13:51 UTC by Rob Taylor
Modified: 2008-10-09 21:05 UTC
See Also:
GNOME target: ---
GNOME version: Unversioned Enhancement


Attachments
Path to add g_sequence_find and g_sequence_find_iter (8.09 KB, patch)
2008-08-20 13:52 UTC, Rob Taylor
none Details | Review
Updated patch with test added (6.80 KB, patch)
2008-09-08 11:26 UTC, Rob Taylor
none Details | Review
Really with the testcase this time, I hope (8.94 KB, patch)
2008-09-08 21:45 UTC, Rob Taylor
none Details | Review
Testcase (3.00 KB, text/x-csrc)
2008-10-05 09:23 UTC, Rob Taylor
  Details

Description Rob Taylor 2008-08-20 13:51:16 UTC
This patch adds the functions g_sequence_find and g_sequence_find_iter. These allow you to search for a given data in the sequence, returning NULL if that data isn't there. The currently available g_sequence_search does not give you any way of telling if a given data is already in the sequence, it only lets you see where the data would be inserted. A user could do this by iterating the sequence like its a list, but as its a balanceed btree undreneath it should expose this for efficiency.

This patch makes me like GSequence again =)
Comment 1 Rob Taylor 2008-08-20 13:52:21 UTC
Created attachment 117051 [details] [review]
Path to add g_sequence_find and g_sequence_find_iter
Comment 2 Sven Herzberg 2008-09-06 01:59:51 UTC
glib/tests/gsequence-test.c seems to be missing
Comment 3 Rob Taylor 2008-09-08 11:26:50 UTC
Created attachment 118293 [details] [review]
Updated patch with test added

I've also removed the autofoo changes to get glib to work with libtool 2.2. I'll attach these in another bug.
Comment 4 Sven Herzberg 2008-09-08 17:00:59 UTC
Forgive me if I'm just too stupid, but where the testcase part in this patch? It still only contains the glib/tests/Makefile.am changes and not the actual testcase.
Comment 5 Rob Taylor 2008-09-08 21:44:10 UTC
oh, hmm, you're quite right, I must have been stupid when removing the autofoo from the diff. 
Comment 6 Rob Taylor 2008-09-08 21:45:22 UTC
Created attachment 118332 [details] [review]
Really with the testcase this time, I hope
Comment 7 Soren Sandmann Pedersen 2008-09-30 19:00:43 UTC
The obvious first question is why can't you just dereference the iter returned from g_sequence_search() and see if it contains the data in question?

Comment 8 Soren Sandmann Pedersen 2008-09-30 19:27:18 UTC
g_sequence_search() returns a pointer to the first position *after* the searched-for data (this fact could be documented and added to the test suite), so g_sequence_find() can be written like this:

GSequenceIter *
g_sequence_find ()
{
    iter = g_sequence_search()
   
    iter = g_sequence_prev()

    if (compare (iter, needle) == 0)
        return iter;

    return NULL;
}

Hence, applications can do it themselves.
Comment 9 Rob Taylor 2008-09-30 19:48:44 UTC
No, that doesn't work. Maybe it should, but it doesn't.

if you don't believe me, try it..

I'll reply with more technical details of why this doesn't work when I have more time and brain.
Comment 10 Rob Taylor 2008-09-30 23:04:44 UTC
Right, more time and brain now :)

The case where this doesn't work is if your sort function is not totally ordered - i.e. if multiple items compare as identical (cmp_func returns 0). One common use case here is sorting on date or string.

I guess its possible to iterate the g_sequence_priv, using the compare function to check that the items are compare-function-wise-identical, but that's starting to get a bit non-obvious IMHO.
Comment 11 Soren Sandmann Pedersen 2008-10-01 06:59:06 UTC
If multiple items compare equal to the item passed in, they will be stored next to each other in the sequence, so the pseudo-code I wrote above will still work because g_sequence_search() returns a pointer to the first position after the set of items that compare equal.
Comment 12 Rob Taylor 2008-10-05 09:20:10 UTC
To save me arguing, I'm attaching a testcase that shows the issue with your suggestion.
Comment 13 Rob Taylor 2008-10-05 09:23:04 UTC
Created attachment 119944 [details]
Testcase
Comment 14 Soren Sandmann Pedersen 2008-10-06 16:44:13 UTC
This testcase mixes two comparison functions: strncmp() and ==, which can't work. 

When you use your "sorter" function, the GSequence has no way of telling the difference between "test1_1" and "test1_2", so you can't expect to find any particular one of them when you search for "test1_1". The sequence_find() in your patch wouldn't work either because it doesn't walk all the items that compared equal.

For what it sounds like you are trying to do, you will need to take the actual pointer into account in the sorting function. Ie., something like this (uncompiled) code:

static gint sorter (gconstpointer a, gconstpointer b, gpointer user_data)
{
        int c;
	const char *str1 = a;
	const char *str2 = b;
	printf ("comparing %s (%p) to %s (%p)\n", str1, str1, str2,str2);
	c = strncmp (str1, str2,5);

        if (c == 0)
        {
            gssize ia = (gssize)a;
            gssize ib = (gssize)b;

            if (ia == ib) return 0;
            else if (ia > ib) return 1;
            else return -1;
        }
        else return c;
}

This will sort by the string value, but if the string value is identical, it will compare the pointers.
Comment 15 Rob Taylor 2008-10-09 16:10:27 UTC
Ah, that makes sense. I'll close the bug.

I wonder if we should add some documentation about these things. If Sven and myself both got the wrong end of the stick, then I'm sure someone else will ;)
Comment 16 Soren Sandmann Pedersen 2008-10-09 21:05:24 UTC
I would make sense to document and test in sequence-test.c that 

    g_sequence_insert_sorted()
    g_sequence_insert_sorted_ite()
    g_sequence_search() 
    etc.

all insert after the last item that compares equal to the one that is being inserted. It's not a coincidence that the code does this already: it makes repeatedly calling g_sequence_insert_sorted() a stable sort.