[geany/geany] 6ba3bb: Don't pass arguments to search/sort functions using static variables
Jiří Techet
git-noreply at xxxxx
Thu Oct 30 21:08:17 UTC 2014
Branch: refs/heads/master
Author: Jiří Techet <techet at gmail.com>
Committer: Jiří Techet <techet at gmail.com>
Date: Thu, 30 Oct 2014 21:08:17 UTC
Commit: 6ba3bb46a455040a8780fd494a99d080913800d9
https://github.com/geany/geany/commit/6ba3bb46a455040a8780fd494a99d080913800d9
Log Message:
-----------
Don't pass arguments to search/sort functions using static variables
Instead of qsort() it's possible to use g_ptr_array_sort_with_data() with
similar performance. Unfortunately it seems there's no bsearch_with_data()
anywhere so the patch uses a modified bsearch() implementation from libc
(still probably cleaner than passing arguments using static variables).
Modified Paths:
--------------
tagmanager/src/tm_tag.c
Modified: tagmanager/src/tm_tag.c
99 lines changed, 65 insertions(+), 34 deletions(-)
===================================================================
@@ -99,8 +99,11 @@ enum
TA_POINTER
};
-static guint *s_sort_attrs = NULL;
-static gboolean s_partial = FALSE;
+typedef struct
+{
+ guint *sort_attrs;
+ gboolean partial;
+} TMSortOptions;
static const char *s_tag_type_names[] = {
"class", /* classes */
@@ -664,36 +667,35 @@ TMTag *tm_tag_ref(TMTag *tag)
}
/*
- Inbuilt tag comparison function. Do not call directly since it needs some
- static variables to be set. Always use tm_tags_sort() and tm_tags_dedup()
- instead.
+ Inbuilt tag comparison function.
*/
-static int tm_tag_compare(const void *ptr1, const void *ptr2)
+static gint tm_tag_compare(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
{
unsigned int *sort_attr;
int returnval = 0;
TMTag *t1 = *((TMTag **) ptr1);
TMTag *t2 = *((TMTag **) ptr2);
+ TMSortOptions *sort_options = user_data;
if ((NULL == t1) || (NULL == t2))
{
g_warning("Found NULL tag");
return t2 - t1;
}
- if (NULL == s_sort_attrs)
+ if (NULL == sort_options->sort_attrs)
{
- if (s_partial)
+ if (sort_options->partial)
return strncmp(FALLBACK(t1->name, ""), FALLBACK(t2->name, ""), strlen(FALLBACK(t1->name, "")));
else
return strcmp(FALLBACK(t1->name, ""), FALLBACK(t2->name, ""));
}
- for (sort_attr = s_sort_attrs; *sort_attr != tm_tag_attr_none_t; ++ sort_attr)
+ for (sort_attr = sort_options->sort_attrs; *sort_attr != tm_tag_attr_none_t; ++ sort_attr)
{
switch (*sort_attr)
{
case tm_tag_attr_name_t:
- if (s_partial)
+ if (sort_options->partial)
returnval = strncmp(FALLBACK(t1->name, ""), FALLBACK(t2->name, ""), strlen(FALLBACK(t1->name, "")));
else
returnval = strcmp(FALLBACK(t1->name, ""), FALLBACK(t2->name, ""));
@@ -761,15 +763,16 @@ gboolean tm_tags_prune(GPtrArray *tags_array)
*/
gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes)
{
+ TMSortOptions sort_options;
guint i;
if ((!tags_array) || (!tags_array->len))
return TRUE;
- s_sort_attrs = sort_attributes;
- s_partial = FALSE;
+ sort_options.sort_attrs = sort_attributes;
+ sort_options.partial = FALSE;
for (i = 1; i < tags_array->len; ++i)
{
- if (0 == tm_tag_compare(&(tags_array->pdata[i - 1]), &(tags_array->pdata[i])))
+ if (0 == tm_tag_compare(&(tags_array->pdata[i - 1]), &(tags_array->pdata[i]), &sort_options))
{
tags_array->pdata[i-1] = NULL;
}
@@ -788,12 +791,13 @@ gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes)
*/
gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean dedup)
{
+ TMSortOptions sort_options;
+
if ((!tags_array) || (!tags_array->len))
return TRUE;
- s_sort_attrs = sort_attributes;
- s_partial = FALSE;
- qsort(tags_array->pdata, tags_array->len, sizeof(gpointer), tm_tag_compare);
- s_sort_attrs = NULL;
+ sort_options.sort_attrs = sort_attributes;
+ sort_options.partial = FALSE;
+ g_ptr_array_sort_with_data(tags_array, tm_tag_compare, &sort_options);
if (dedup)
tm_tags_dedup(tags_array, sort_attributes);
return TRUE;
@@ -817,7 +821,7 @@ void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array)
* The merge complexity depends mostly on the size of the small array
* and is almost independent of the size of the big array.
* In addition, get rid of the duplicates (if both big_array and small_array are duplicate-free). */
-static GPtrArray *merge(GPtrArray *big_array, GPtrArray *small_array) {
+static GPtrArray *merge(GPtrArray *big_array, GPtrArray *small_array, TMSortOptions *sort_options) {
guint i1 = 0; /* index to big_array */
guint i2 = 0; /* index to small_array */
guint initial_step;
@@ -858,7 +862,7 @@ static GPtrArray *merge(GPtrArray *big_array, GPtrArray *small_array) {
/* if the value in big_array after making the big step is still smaller
* than the value in small_array, we can copy all the values inbetween
* into the result without making expensive string comparisons */
- if (tm_tag_compare(&val1, &val2) < 0)
+ if (tm_tag_compare(&val1, &val2, sort_options) < 0)
{
while (i1 <= j1)
{
@@ -881,7 +885,7 @@ static GPtrArray *merge(GPtrArray *big_array, GPtrArray *small_array) {
cmpnum++;
#endif
val1 = big_array->pdata[i1];
- cmpval = tm_tag_compare(&val1, &val2);
+ cmpval = tm_tag_compare(&val1, &val2, sort_options);
if (cmpval < 0)
{
g_ptr_array_add(res_array, val1);
@@ -917,11 +921,11 @@ static GPtrArray *merge(GPtrArray *big_array, GPtrArray *small_array) {
GPtrArray *tm_tags_merge(GPtrArray *big_array, GPtrArray *small_array, TMTagAttrType *sort_attributes)
{
GPtrArray *res_array;
+ TMSortOptions sort_options;
- s_sort_attrs = sort_attributes;
- s_partial = FALSE;
- res_array = merge(big_array, small_array);
- s_sort_attrs = NULL;
+ sort_options.sort_attrs = sort_attributes;
+ sort_options.partial = FALSE;
+ res_array = merge(big_array, small_array, &sort_options);
return res_array;
}
@@ -973,13 +977,40 @@ void tm_tags_array_free(GPtrArray *tags_array, gboolean free_all)
}
}
+/* copy/pasted bsearch() from libc extended with user_data for comparison function
+ * and using glib types */
+static gpointer binary_search(gpointer key, gpointer base, size_t nmemb,
+ GCompareDataFunc compar, gpointer user_data)
+{
+ gsize l, u, idx;
+ gpointer p;
+ gint comparison;
+
+ l = 0;
+ u = nmemb;
+ while (l < u)
+ {
+ idx = (l + u) / 2;
+ p = (gpointer) (((const gchar *) base) + (idx * sizeof(gpointer)));
+ comparison = (*compar) (key, p, user_data);
+ if (comparison < 0)
+ u = idx;
+ else if (comparison > 0)
+ l = idx + 1;
+ else
+ return (gpointer) p;
+ }
+
+ return NULL;
+}
+
static TMTag **tags_search(const GPtrArray *tags_array, TMTag *tag, gboolean partial,
- gboolean tags_array_sorted)
+ gboolean tags_array_sorted, TMSortOptions *sort_options)
{
if (tags_array_sorted)
{ /* fast binary search on sorted tags array */
- return (TMTag **) bsearch(&tag, tags_array->pdata, tags_array->len
- , sizeof(gpointer), tm_tag_compare);
+ return (TMTag **) binary_search(&tag, tags_array->pdata, tags_array->len,
+ tm_tag_compare, sort_options);
}
else
{ /* the slow way: linear search (to make it a bit faster, search reverse assuming
@@ -989,7 +1020,7 @@ static TMTag **tags_search(const GPtrArray *tags_array, TMTag *tag, gboolean par
for (i = tags_array->len - 1; i >= 0; i--)
{
t = (TMTag **) &tags_array->pdata[i];
- if (0 == tm_tag_compare(&tag, t))
+ if (0 == tm_tag_compare(&tag, t, sort_options))
return t;
}
}
@@ -1013,6 +1044,7 @@ TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
static TMTag *tag = NULL;
TMTag **result;
int tagMatches=0;
+ TMSortOptions sort_options;
if ((!tags_array) || (!tags_array->len))
return NULL;
@@ -1020,10 +1052,10 @@ TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
if (NULL == tag)
tag = g_new0(TMTag, 1);
tag->name = (char *) name;
- s_sort_attrs = NULL;
- s_partial = partial;
+ sort_options.sort_attrs = NULL;
+ sort_options.partial = partial;
- result = tags_search(tags_array, tag, partial, tags_array_sorted);
+ result = tags_search(tags_array, tag, partial, tags_array_sorted, &sort_options);
/* There can be matches on both sides of result */
if (result)
{
@@ -1035,21 +1067,20 @@ TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
adv++;
for (; adv <= last && *adv; ++ adv)
{
- if (0 != tm_tag_compare(&tag, adv))
+ if (0 != tm_tag_compare(&tag, adv, &sort_options))
break;
++tagMatches;
}
/* Now look for matches from result and below */
for (; result >= (TMTag **) tags_array->pdata; -- result)
{
- if (0 != tm_tag_compare(&tag, (TMTag **) result))
+ if (0 != tm_tag_compare(&tag, (TMTag **) result, &sort_options))
break;
++tagMatches;
}
*tagCount=tagMatches;
++ result; /* Correct address for the last successful match */
}
- s_partial = FALSE;
return (TMTag **) result;
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list