summaryrefslogtreecommitdiff
path: root/glib/gsequence.c
diff options
context:
space:
mode:
Diffstat (limited to 'glib/gsequence.c')
-rw-r--r--glib/gsequence.c138
1 files changed, 137 insertions, 1 deletions
diff --git a/glib/gsequence.c b/glib/gsequence.c
index 8b28ce79a..40b3294d7 100644
--- a/glib/gsequence.c
+++ b/glib/gsequence.c
@@ -133,6 +133,11 @@ static GSequenceNode *node_get_next (GSequenceNode *node);
static gint node_get_pos (GSequenceNode *node);
static GSequenceNode *node_get_by_pos (GSequenceNode *node,
gint pos);
+static GSequenceNode *node_find (GSequenceNode *haystack,
+ GSequenceNode *needle,
+ GSequenceNode *end,
+ GSequenceIterCompareFunc cmp,
+ gpointer user_data);
static GSequenceNode *node_find_closest (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
@@ -756,6 +761,9 @@ g_sequence_sort_changed (GSequenceIter *iter,
* Returns an iterator pointing to the position where @data would
* be inserted according to @cmp_func and @cmp_data.
*
+ * If you are simply searching for an existing element of the sequence,
+ * consider using g_sequence_lookup().
+ *
* Return value: an #GSequenceIter pointing to the position where @data
* would have been inserted according to @cmp_func and @cmp_data.
*
@@ -780,6 +788,46 @@ g_sequence_search (GSequence *seq,
}
/**
+ * g_sequence_lookup:
+ * @seq: a #GSequence
+ * @data: data to lookup
+ * @cmp_func: the #GCompareDataFunc used to compare items in the sequence. It
+ * is called with two items of the @seq and @user_data. It should
+ * return 0 if the items are equal, a negative value if the first
+ * item comes before the second, and a positive value if the second
+ * item comes before the first.
+ * @cmp_data: user data passed to @cmp_func.
+ *
+ * Returns an iterator pointing to the position of the first item found
+ * equal to @data according to @cmp_func and @cmp_data. If more than one item
+ * is equal, it is not guaranteed that it is the first which is returned.
+ * In that case, you can use g_sequence_iter_next() and g_sequence_iter_prev()
+ * to get others.
+ *
+ * Return value: an #GSequenceIter pointing to the position of the first item
+ * found equal to @data according to @cmp_func and @cmp_data.
+ *
+ * Since: 2.26
+ **/
+GSequenceIter *
+g_sequence_lookup (GSequence *seq,
+ gpointer data,
+ GCompareDataFunc cmp_func,
+ gpointer cmp_data)
+{
+ SortInfo info;
+
+ g_return_val_if_fail (seq != NULL, NULL);
+
+ info.cmp_func = cmp_func;
+ info.cmp_data = cmp_data;
+ info.end_node = seq->end_node;
+ check_seq_access (seq);
+
+ return g_sequence_lookup_iter (seq, data, iter_compare, &info);
+}
+
+/**
* g_sequence_sort_iter:
* @seq: a #GSequence
* @cmp_func: the #GSequenceItercompare used to compare iterators in the
@@ -970,6 +1018,9 @@ g_sequence_insert_sorted_iter (GSequence *seq,
* a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
* the compare function.
*
+ * If you are simply searching for an existing element of the sequence,
+ * consider using g_sequence_lookup_iter().
+ *
* Return value: a #GSequenceIter pointing to the position in @seq
* where @data would have been inserted according to @iter_cmp and @cmp_data.
*
@@ -1007,6 +1058,57 @@ g_sequence_search_iter (GSequence *seq,
}
/**
+ * g_sequence_lookup_iter:
+ * @seq: a #GSequence
+ * @data: data to lookup
+ * @iter_cmp: the #GSequenceIterCompare function used to compare iterators
+ * in the sequence. It is called with two iterators pointing into @seq.
+ * It should return 0 if the iterators are equal, a negative value if the
+ * first iterator comes before the second, and a positive value if the
+ * second iterator comes before the first.
+ * @cmp_data: user data passed to @iter_cmp
+ *
+ * Like g_sequence_lookup(), but uses
+ * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
+ * the compare function.
+ *
+ * Return value: an #GSequenceIter pointing to the position of the first item
+ * found equal to @data according to @cmp_func and @cmp_data.
+ *
+ * Since: 2.26
+ **/
+GSequenceIter *
+g_sequence_lookup_iter (GSequence *seq,
+ gpointer data,
+ GSequenceIterCompareFunc iter_cmp,
+ gpointer cmp_data)
+{
+ GSequenceNode *node;
+ GSequenceNode *dummy;
+ GSequence *tmp_seq;
+
+ g_return_val_if_fail (seq != NULL, NULL);
+
+ check_seq_access (seq);
+
+ seq->access_prohibited = TRUE;
+
+ tmp_seq = g_sequence_new (NULL);
+ tmp_seq->real_sequence = seq;
+
+ dummy = g_sequence_append (tmp_seq, data);
+
+ node = node_find (seq->end_node, dummy,
+ seq->end_node, iter_cmp, cmp_data);
+
+ g_sequence_free (tmp_seq);
+
+ seq->access_prohibited = FALSE;
+
+ return node;
+}
+
+/**
* g_sequence_iter_get_sequence:
* @iter: a #GSequenceIter
*
@@ -1549,6 +1651,40 @@ node_get_by_pos (GSequenceNode *node,
}
static GSequenceNode *
+node_find (GSequenceNode *haystack,
+ GSequenceNode *needle,
+ GSequenceNode *end,
+ GSequenceIterCompareFunc iter_cmp,
+ gpointer cmp_data)
+{
+ gint c;
+
+ haystack = find_root (haystack);
+
+ do
+ {
+ /* iter_cmp can't be passed the end node, since the function may
+ * be user-supplied
+ */
+ if (haystack == end)
+ c = 1;
+ else
+ c = iter_cmp (haystack, needle, cmp_data);
+
+ if (c == 0)
+ break;
+
+ if (c > 0)
+ haystack = haystack->left;
+ else
+ haystack = haystack->right;
+ }
+ while (haystack != NULL);
+
+ return haystack;
+}
+
+static GSequenceNode *
node_find_closest (GSequenceNode *haystack,
GSequenceNode *needle,
GSequenceNode *end,
@@ -1572,7 +1708,7 @@ node_find_closest (GSequenceNode *haystack,
else
c = iter_cmp (haystack, needle, cmp_data);
- /* In the following we don't break even if c == 0. Instaed we go on
+ /* In the following we don't break even if c == 0. Instead we go on
* searching along the 'bigger' nodes, so that we find the last one
* that is equal to the needle.
*/