hostname complition: refactoring: use GPtrArray.

This commit is contained in:
Andrew Borodin 2024-03-31 19:40:09 +03:00
parent 1c7da890bf
commit 4929248f30
3 changed files with 106 additions and 45 deletions

View File

@ -44,12 +44,87 @@
/*** file scope variables ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
#if ! GLIB_CHECK_VERSION (2, 54, 0)
/**
* g_direct_equal:
* @v1: (nullable): a key
* @v2: (nullable): a key to compare with @v1
*
* Compares two #gpointer arguments and returns %TRUE if they are equal.
* It can be passed to g_hash_table_new() as the @key_equal_func
* parameter, when using opaque pointers compared by pointer value as
* keys in a #GHashTable.
*
* This equality function is also appropriate for keys that are integers
* stored in pointers, such as `GINT_TO_POINTER (n)`.
*
* Returns: %TRUE if the two keys match.
*/
static gboolean
g_direct_equal (gconstpointer v1, gconstpointer v2)
{
return v1 == v2;
}
#endif /* ! GLIB_CHECK_VERSION (2, 54, 0) */
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
#if ! GLIB_CHECK_VERSION (2, 54, 0)
/**
* g_ptr_array_find_with_equal_func: (skip)
* @haystack: pointer array to be searched
* @needle: pointer to look for
* @equal_func: (nullable): the function to call for each element, which should
* return %TRUE when the desired element is found; or %NULL to use pointer
* equality
* @index_: (optional) (out): return location for the index of
* the element, if found
*
* Checks whether @needle exists in @haystack, using the given @equal_func.
* If the element is found, %TRUE is returned and the element^A^A^As index is
* returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_
* is undefined. If @needle exists multiple times in @haystack, the index of
* the first instance is returned.
*
* @equal_func is called with the element from the array as its first parameter,
* and @needle as its second parameter. If @equal_func is %NULL, pointer
* equality is used.
*
* Returns: %TRUE if @needle is one of the elements of @haystack
* Since: 2.54
*/
gboolean
g_ptr_array_find_with_equal_func (GPtrArray * haystack, gconstpointer needle, GEqualFunc equal_func,
guint * index_)
{
guint i;
g_return_val_if_fail (haystack != NULL, FALSE);
if (equal_func == NULL)
equal_func = g_direct_equal;
for (i = 0; i < haystack->len; i++)
if (equal_func (g_ptr_array_index (haystack, i), needle))
{
if (index_ != NULL)
*index_ = i;
return TRUE;
}
return FALSE;
}
#endif /* ! GLIB_CHECK_VERSION (2, 54, 0) */
/* --------------------------------------------------------------------------------------------- */
#if ! GLIB_CHECK_VERSION (2, 63, 3)
/**
* g_clear_slist: (skip)

View File

@ -16,6 +16,11 @@
/*** declarations of public functions ************************************************************/
#if ! GLIB_CHECK_VERSION (2, 54, 0)
gboolean g_ptr_array_find_with_equal_func (GPtrArray * haystack, gconstpointer needle,
GEqualFunc equal_func, guint * index_);
#endif /* ! GLIB_CHECK_VERSION (2, 54, 0) */
#if ! GLIB_CHECK_VERSION (2, 63, 3)
void g_clear_slist (GSList ** slist_ptr, GDestroyNotify destroy);
void g_clear_list (GList ** list_ptr, GDestroyNotify destroy);

View File

@ -93,10 +93,6 @@ void complete_engine_fill_completions (WInput * in);
/*** file scope variables ************************************************************************/
static char **hosts = NULL;
static char **hosts_p = NULL;
static int hosts_alloclen = 0;
static WInput *input;
static int min_end;
static int start = 0;
@ -394,8 +390,16 @@ variable_completion_function (const char *text, int state, input_complete_t flag
/* --------------------------------------------------------------------------------------------- */
static gboolean
host_equal_func (gconstpointer a, gconstpointer b)
{
return (strcmp ((const char *) a, (const char *) b) == 0);
}
/* --------------------------------------------------------------------------------------------- */
static void
fetch_hosts (const char *filename)
fetch_hosts (const char *filename, GPtrArray * hosts)
{
FILE *file;
char buffer[256];
@ -433,7 +437,7 @@ fetch_hosts (const char *filename)
str_next_char (&t);
*t = '\0';
fetch_hosts (includefile);
fetch_hosts (includefile, hosts);
continue;
}
@ -455,32 +459,10 @@ fetch_hosts (const char *filename)
continue;
name = g_strndup (lc_start, bi - lc_start);
{
char **host_p;
int j;
j = hosts_p - hosts;
if (j >= hosts_alloclen)
{
hosts_alloclen += 30;
hosts = g_renew (char *, hosts, hosts_alloclen + 1);
hosts_p = hosts + j;
}
for (host_p = hosts; host_p < hosts_p; host_p++)
if (strcmp (name, *host_p) == 0)
break; /* We do not want any duplicates */
if (host_p == hosts_p)
{
*(hosts_p++) = name;
*hosts_p = NULL;
}
else
g_free (name);
}
if (!g_ptr_array_find_with_equal_func (hosts, name, host_equal_func, NULL))
g_ptr_array_add (hosts, name);
else
g_free (name);
}
}
@ -492,7 +474,8 @@ fetch_hosts (const char *filename)
static char *
hostname_completion_function (const char *text, int state, input_complete_t flags)
{
static char **host_p = NULL;
static GPtrArray *hosts = NULL;
static unsigned int host_p = 0;
static size_t textstart = 0;
static size_t textlen = 0;
@ -503,29 +486,27 @@ hostname_completion_function (const char *text, int state, input_complete_t flag
{ /* Initialization stuff */
const char *p;
g_strfreev (hosts);
hosts_alloclen = 30;
hosts = g_new (char *, hosts_alloclen + 1);
*hosts = NULL;
hosts_p = hosts;
if (hosts != NULL)
g_ptr_array_free (hosts, TRUE);
hosts = g_ptr_array_new_with_free_func (g_free);
p = getenv ("HOSTFILE");
fetch_hosts (p != NULL ? p : "/etc/hosts");
host_p = hosts;
fetch_hosts (p != NULL ? p : "/etc/hosts", hosts);
host_p = 0;
textstart = (*text == '@') ? 1 : 0;
textlen = strlen (text + textstart);
}
for (; *host_p != NULL; host_p++)
for (; host_p < hosts->len; host_p++)
{
if (textlen == 0)
break; /* Match all of them */
if (strncmp (text + textstart, *host_p, textlen) == 0)
if (strncmp (text + textstart, g_ptr_array_index (hosts, host_p), textlen) == 0)
break;
}
if (*host_p == NULL)
if (host_p == hosts->len)
{
g_strfreev (hosts);
g_ptr_array_free (hosts, TRUE);
hosts = NULL;
return NULL;
}
@ -537,7 +518,7 @@ hostname_completion_function (const char *text, int state, input_complete_t flag
if (textstart != 0)
g_string_append_c (temp, '@');
g_string_append (temp, *host_p);
g_string_append (temp, g_ptr_array_index (hosts, host_p));
host_p++;
return g_string_free (temp, FALSE);