Commit e259b2f3 authored by Emmanuele Bassi's avatar Emmanuele Bassi

Avoid O(n²) walking of string arrays

"Yo, we heard you like traversing NULL-terminated arrays to operate on
them, so we called g_strv_length() as the for condition, so you can
iterate the array while iterating the array."

Instead of making famed rapper and television producer Xzibit proud, we
should avoid calling g_strv_length() on an array while looping on the
array, to avoid quadratic complexity.

We do this in various places that deal with arrays of strings that we
cannot really guess are short enough not to matter — e.g. the list of
CSS selectors in the inspector, or the required authentication
information for printing.
parent 3b41daca
......@@ -706,24 +706,27 @@ password_dialog_response (GtkWidget *dialog,
GtkPrintBackend *backend)
{
GtkPrintBackendPrivate *priv = backend->priv;
gint i;
gint i, auth_info_len;
if (response_id == GTK_RESPONSE_OK)
gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
else
gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
if (priv->auth_info[i] != NULL)
{
memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
g_free (priv->auth_info[i]);
priv->auth_info[i] = NULL;
}
g_free (priv->auth_info);
priv->auth_info = NULL;
/* We want to clear the data before freeing it */
auth_info_len = g_strv_length (priv->auth_info_required);
for (i = 0; i < auth_info_len; i++)
{
if (priv->auth_info[i] != NULL)
{
memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
g_free (priv->auth_info[i]);
priv->auth_info[i] = NULL;
}
}
g_strfreev (priv->auth_info_required);
g_clear_pointer (&priv->auth_info, g_free);
g_clear_pointer (&priv->auth_info_required, g_strfreev);
gtk_widget_destroy (dialog);
......
......@@ -64,7 +64,7 @@ gtk_inspector_selector_set_object (GtkInspectorSelector *oh,
GObject *object)
{
GtkTreeIter iter, parent;
gint i;
gint i, words_len;
GtkWidget *widget;
gchar *path, **words;
const gchar *title;
......@@ -85,7 +85,8 @@ gtk_inspector_selector_set_object (GtkInspectorSelector *oh,
path = gtk_widget_path_to_string (gtk_widget_get_path (widget));
words = g_strsplit (path, " ", 0);
for (i = 0; i < g_strv_length (words); i++)
words_len = g_strv_length (words);
for (i = 0; i < words_len; i++)
{
gtk_tree_store_append (oh->priv->model, &iter, i ? &parent : NULL);
gtk_tree_store_set (oh->priv->model, &iter,
......
......@@ -109,7 +109,7 @@ get_secret_cb (GObject *source_object,
*key = NULL,
*value = NULL;
GVariantIter *iter = NULL;
guint i;
guint i, required_len;
gint pw_field = -1;
task = user_data;
......@@ -228,7 +228,8 @@ get_secret_cb (GObject *source_object,
fail:
/* Error out */
GTK_NOTE (PRINTING, g_print ("Failed to lookup secret.\n"));
for (i = 0; i < g_strv_length (task_data->auth_info_required); i++)
required_len = g_strv_length (task_data->auth_info_required);
for (i = 0; i < required_len; i++)
{
/* Not all fields of auth_info are neccessarily written so we can not
use strfreev here */
......
......@@ -142,7 +142,7 @@ record_events (const gchar *ui_file,
GError *error;
gchar *contents;
gchar **actions;
gint i;
gint i, len;
builder = gtk_builder_new ();
error = NULL;
......@@ -152,8 +152,9 @@ record_events (const gchar *ui_file,
g_file_get_contents (in_file, &contents, NULL, &error);
g_assert_no_error (error);
actions = g_strsplit (contents, "\n", 0);
for (i = 0; i < g_strv_length (actions); i++)
len = g_strv_length (actions);
for (i = 0; i < len; i++)
do_action (builder, actions[i], string);
g_object_unref (builder);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment