From b9d1b5d6a32385d3c578714aa843a0d21a7be736 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 21:18:56 -0500 Subject: [PATCH 1/8] icontheme: Bit a bit less wasteful --- gtk/gtkicontheme.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index fc3eb09165..e98240c010 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -1715,7 +1715,6 @@ insert_theme (GtkIconTheme *self, IconTheme *theme = NULL; char *path; GKeyFile *theme_file; - GError *error = NULL; GStatBuf stat_buf; for (l = self->themes; l != NULL; l = l->next) @@ -1725,6 +1724,7 @@ insert_theme (GtkIconTheme *self, return; } + theme_file = NULL; for (i = 0; self->search_path[i]; i++) { IconThemeDirMtime dir_mtime; @@ -1736,6 +1736,22 @@ insert_theme (GtkIconTheme *self, { dir_mtime.mtime = stat_buf.st_mtime; dir_mtime.exists = TRUE; + + if (!theme_file) + { + char *file = g_build_filename (path, "index.theme", NULL); + if (g_file_test (file, G_FILE_TEST_IS_REGULAR)) + { + theme_file = g_key_file_new (); + g_key_file_set_list_separator (theme_file, ','); + if (!g_key_file_load_from_file (theme_file, file, 0, NULL)) + { + g_key_file_free (theme_file); + theme_file = NULL; + } + } + g_free (file); + } } else { @@ -1746,25 +1762,6 @@ insert_theme (GtkIconTheme *self, g_array_insert_val (self->dir_mtimes, 0, dir_mtime); } - theme_file = NULL; - for (i = 0; self->search_path[i] && !theme_file; i++) - { - path = g_build_filename (self->search_path[i], theme_name, "index.theme", NULL); - if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) - { - theme_file = g_key_file_new (); - g_key_file_set_list_separator (theme_file, ','); - if (!g_key_file_load_from_file (theme_file, path, 0, &error)) - { - g_key_file_free (theme_file); - theme_file = NULL; - g_error_free (error); - error = NULL; - } - } - g_free (path); - } - if (theme_file == NULL) { if (strcmp (theme_name, FALLBACK_ICON_THEME) == 0) From c9fca559dc01cc47e4194c6cdd291517979141d1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 22:53:39 -0500 Subject: [PATCH 2/8] Cosmetics --- gtk/css/gtkcsstokenizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk/css/gtkcsstokenizer.c b/gtk/css/gtkcsstokenizer.c index a6d14abc21..4d405539e6 100644 --- a/gtk/css/gtkcsstokenizer.c +++ b/gtk/css/gtkcsstokenizer.c @@ -1145,7 +1145,7 @@ gtk_css_tokenizer_read_numeric (GtkCssTokenizer *tokenizer, else type = has_sign ? GTK_CSS_TOKEN_SIGNED_NUMBER : GTK_CSS_TOKEN_SIGNLESS_NUMBER; - gtk_css_token_init_number (token, type,value); + gtk_css_token_init_number (token, type, value); } } From 0f7d8e04d82d8c7ab31d9261ef856cfc07b8cfec Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 21:18:36 -0500 Subject: [PATCH 3/8] css: Some inlining --- gtk/css/gtkcsslocation.c | 72 --------------------------------- gtk/css/gtkcsslocationprivate.h | 32 ++++++++++++--- gtk/css/gtkcsstokenizer.c | 16 ++++---- gtk/css/meson.build | 1 - 4 files changed, 34 insertions(+), 87 deletions(-) delete mode 100644 gtk/css/gtkcsslocation.c diff --git a/gtk/css/gtkcsslocation.c b/gtk/css/gtkcsslocation.c deleted file mode 100644 index 41725ad2fe..0000000000 --- a/gtk/css/gtkcsslocation.c +++ /dev/null @@ -1,72 +0,0 @@ -/* GSK - The GIMP Toolkit - * Copyright (C) 2019 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#include "config.h" - -#include "gtkcsslocationprivate.h" - -/** - * GtkCssLocation: - * @bytes: number of bytes parsed since the beginning - * @chars: number of characters parsed since the beginning - * @lines: number of full lines that have been parsed. If you want to - * display this as a line number, you need to add 1 to this. - * @line_bytes: Number of bytes parsed since the last line break - * @line_chars: Number of characters parsed since the last line break - * - * Represents a location in a file or other source of data parsed - * by the CSS engine. - * - * The @bytes and @line_bytes offsets are meant to be used to - * programmatically match data. The @lines and @line_chars offsets - * can be used for printing the location in a file. - * - * Note that the @lines parameter starts from 0 and is increased - * whenever a CSS line break is encountered. (CSS defines the C character - * sequences "\r\n", "\r", "\n" and "\f" as newlines.) - * If your document uses different rules for line breaking, you might want - * run into problems here. - */ - -void -gtk_css_location_init (GtkCssLocation *location) -{ - memset (location, 0, sizeof (GtkCssLocation)); -} - -void -gtk_css_location_advance (GtkCssLocation *location, - gsize bytes, - gsize chars) -{ - location->bytes += bytes; - location->chars += chars; - location->line_bytes += bytes; - location->line_chars += chars; -} - -void -gtk_css_location_advance_newline (GtkCssLocation *location, - gboolean is_windows) -{ - gtk_css_location_advance (location, is_windows ? 2 : 1, is_windows ? 2 : 1); - - location->lines++; - location->line_bytes = 0; - location->line_chars = 0; -} - diff --git a/gtk/css/gtkcsslocationprivate.h b/gtk/css/gtkcsslocationprivate.h index 46ed3c8056..89ff0e979e 100644 --- a/gtk/css/gtkcsslocationprivate.h +++ b/gtk/css/gtkcsslocationprivate.h @@ -25,13 +25,33 @@ G_BEGIN_DECLS -void gtk_css_location_init (GtkCssLocation *location); +static inline void +gtk_css_location_init (GtkCssLocation *location) +{ + memset (location, 0, sizeof (GtkCssLocation)); +} -void gtk_css_location_advance (GtkCssLocation *location, - gsize bytes, - gsize chars); -void gtk_css_location_advance_newline (GtkCssLocation *location, - gboolean is_windows); +static inline void +gtk_css_location_advance (GtkCssLocation *location, + gsize bytes, + gsize chars) +{ + location->bytes += bytes; + location->chars += chars; + location->line_bytes += bytes; + location->line_chars += chars; +} + +static inline void +gtk_css_location_advance_newline (GtkCssLocation *location, + gboolean is_windows) +{ + location->bytes += is_windows ? 2 : 1; + location->chars += is_windows ? 2 : 1; + location->line_bytes = 0; + location->line_chars = 0; + location->lines++; +} G_END_DECLS diff --git a/gtk/css/gtkcsstokenizer.c b/gtk/css/gtkcsstokenizer.c index 4d405539e6..262f52a3cd 100644 --- a/gtk/css/gtkcsstokenizer.c +++ b/gtk/css/gtkcsstokenizer.c @@ -630,7 +630,7 @@ gtk_css_tokenizer_parse_error (GError **error, va_end (args); } -static gboolean +static inline gboolean is_newline (char c) { return c == '\n' @@ -638,7 +638,7 @@ is_newline (char c) || c == '\f'; } -static gboolean +static inline gboolean is_whitespace (char c) { return is_newline (c) @@ -646,13 +646,13 @@ is_whitespace (char c) || c == ' '; } -static gboolean +static inline gboolean is_multibyte (char c) { return c & 0x80; } -static gboolean +static inline gboolean is_name_start (char c) { return is_multibyte (c) @@ -660,7 +660,7 @@ is_name_start (char c) || c == '_'; } -static gboolean +static inline gboolean is_name (char c) { return is_name_start (c) @@ -668,7 +668,7 @@ is_name (char c) || c == '-'; } -static gboolean +static inline gboolean is_non_printable (char c) { return (c >= 0 && c <= 0x08) @@ -678,7 +678,7 @@ is_non_printable (char c) || c == 0x7F; } -static gboolean +static inline gboolean is_valid_escape (const char *data, const char *end) { @@ -703,7 +703,7 @@ gtk_css_tokenizer_remaining (GtkCssTokenizer *tokenizer) return tokenizer->end - tokenizer->data; } -static gboolean +static inline gboolean gtk_css_tokenizer_has_valid_escape (GtkCssTokenizer *tokenizer) { return is_valid_escape (tokenizer->data, tokenizer->end); diff --git a/gtk/css/meson.build b/gtk/css/meson.build index 2785f41374..bf083f693e 100644 --- a/gtk/css/meson.build +++ b/gtk/css/meson.build @@ -1,5 +1,4 @@ gtk_css_public_sources = files([ - 'gtkcsslocation.c', 'gtkcsserror.c', 'gtkcsssection.c', ]) From 6fb6f47fc8018aa6f525b2dfc117ab10be94363c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 22:02:20 -0500 Subject: [PATCH 4/8] css: Avoid some allocations Reuse the name_buffer for reading strings. --- gtk/css/gtkcsstokenizer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gtk/css/gtkcsstokenizer.c b/gtk/css/gtkcsstokenizer.c index 262f52a3cd..2652b0e994 100644 --- a/gtk/css/gtkcsstokenizer.c +++ b/gtk/css/gtkcsstokenizer.c @@ -1196,7 +1196,8 @@ gtk_css_tokenizer_read_string (GtkCssTokenizer *tokenizer, GtkCssToken *token, GError **error) { - GString *string = g_string_new (NULL); + g_string_set_size (tokenizer->name_buffer, 0); + char end = *tokenizer->data; gtk_css_tokenizer_consume_ascii (tokenizer); @@ -1222,23 +1223,22 @@ gtk_css_tokenizer_read_string (GtkCssTokenizer *tokenizer, } else { - g_string_append_unichar (string, gtk_css_tokenizer_read_escape (tokenizer)); + g_string_append_unichar (tokenizer->name_buffer, gtk_css_tokenizer_read_escape (tokenizer)); } } else if (is_newline (*tokenizer->data)) { - g_string_free (string, TRUE); gtk_css_token_init (token, GTK_CSS_TOKEN_BAD_STRING); gtk_css_tokenizer_parse_error (error, "Newlines inside strings must be escaped"); return FALSE; } else { - gtk_css_tokenizer_consume_char (tokenizer, string); + gtk_css_tokenizer_consume_char (tokenizer, tokenizer->name_buffer); } } - gtk_css_token_init_string (token, GTK_CSS_TOKEN_STRING, g_string_free (string, FALSE)); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_STRING, g_strdup (tokenizer->name_buffer->str)); return TRUE; } From d43e0fb9a72b411550cc4b937f63b89dc0cb74f3 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 23:07:19 -0500 Subject: [PATCH 5/8] css: Avoid allocation for tokens All valid dimensions are short, so store the dimension inside the token. --- gtk/css/gtkcsstokenizer.c | 22 ++++++++++++++-------- gtk/css/gtkcsstokenizerprivate.h | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/gtk/css/gtkcsstokenizer.c b/gtk/css/gtkcsstokenizer.c index 2652b0e994..9cf59e1559 100644 --- a/gtk/css/gtkcsstokenizer.c +++ b/gtk/css/gtkcsstokenizer.c @@ -57,11 +57,6 @@ gtk_css_token_clear (GtkCssToken *token) case GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION: case GTK_CSS_TOKEN_SIGNED_DIMENSION: case GTK_CSS_TOKEN_SIGNLESS_DIMENSION: - g_free (token->dimension.dimension); - break; - - default: - g_assert_not_reached (); case GTK_CSS_TOKEN_EOF: case GTK_CSS_TOKEN_WHITESPACE: case GTK_CSS_TOKEN_OPEN_PARENS: @@ -91,6 +86,9 @@ gtk_css_token_clear (GtkCssToken *token) case GTK_CSS_TOKEN_BAD_URL: case GTK_CSS_TOKEN_COMMENT: break; + + default: + g_assert_not_reached (); } token->type = GTK_CSS_TOKEN_EOF; @@ -545,7 +543,8 @@ static void gtk_css_token_init_dimension (GtkCssToken *token, GtkCssTokenType type, double value, - char *dimension) + const char *dimension, + int len) { token->type = type; @@ -556,7 +555,13 @@ gtk_css_token_init_dimension (GtkCssToken *token, case GTK_CSS_TOKEN_SIGNED_DIMENSION: case GTK_CSS_TOKEN_SIGNLESS_DIMENSION: token->dimension.value = value; - token->dimension.dimension = dimension; + for (int i = 0; i < MIN (8, len); i++) + { + token->dimension.dimension[i] = dimension[i]; + if (dimension[i] == 0) + break; + } + token->dimension.dimension[7] = 0; break; default: g_assert_not_reached (); @@ -1129,7 +1134,8 @@ gtk_css_tokenizer_read_numeric (GtkCssTokenizer *tokenizer, else type = has_sign ? GTK_CSS_TOKEN_SIGNED_DIMENSION : GTK_CSS_TOKEN_SIGNLESS_DIMENSION; - gtk_css_token_init_dimension (token, type, value, gtk_css_tokenizer_read_name (tokenizer)); + char *name = gtk_css_tokenizer_read_name (tokenizer); + gtk_css_token_init_dimension (token, type, value, name, strlen (name)); } else if (gtk_css_tokenizer_remaining (tokenizer) > 0 && *tokenizer->data == '%') { diff --git a/gtk/css/gtkcsstokenizerprivate.h b/gtk/css/gtkcsstokenizerprivate.h index 6211ef722f..6f97bd904e 100644 --- a/gtk/css/gtkcsstokenizerprivate.h +++ b/gtk/css/gtkcsstokenizerprivate.h @@ -97,7 +97,7 @@ struct _GtkCssNumberToken { struct _GtkCssDimensionToken { GtkCssTokenType type; double value; - char *dimension; + char dimension[8]; }; union _GtkCssToken { From 1e7f525e0e2ae361d7db9d71b267496de9adf09c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 11 Jan 2023 23:19:30 -0500 Subject: [PATCH 6/8] css: Avoid some allocations Avoid duplicating the function name just for an error message. --- gtk/css/gtkcssparser.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gtk/css/gtkcssparser.c b/gtk/css/gtkcssparser.c index 7668bfc70e..886e84f952 100644 --- a/gtk/css/gtkcssparser.c +++ b/gtk/css/gtkcssparser.c @@ -642,13 +642,13 @@ gtk_css_parser_consume_function (GtkCssParser *self, { const GtkCssToken *token; gboolean result = FALSE; - char *function_name; + char function_name[64]; guint arg; token = gtk_css_parser_get_token (self); g_return_val_if_fail (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION), FALSE); - function_name = g_strdup (token->string.string); + g_strlcpy (function_name, token->string.string, 64); gtk_css_parser_start_block (self); arg = 0; @@ -691,7 +691,6 @@ gtk_css_parser_consume_function (GtkCssParser *self, } gtk_css_parser_end_block (self); - g_free (function_name); return result; } @@ -756,7 +755,7 @@ gtk_css_parser_has_integer (GtkCssParser *self) * Checks if the next token is a function with the given @name. * * Returns: %TRUE if the next token is a function with the given @name - **/ + */ gboolean gtk_css_parser_has_function (GtkCssParser *self, const char *name) From 46e0fde60674da6963e0236ce13844cf2fb64802 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 12 Jan 2023 00:00:54 -0500 Subject: [PATCH 7/8] css: Avoid more allocations for tokens Make short string tokens static. --- gdk/gdkrgba.c | 6 +-- gsk/gskrendernodeparser.c | 6 +-- gtk/css/gtkcssparser.c | 16 +++---- gtk/css/gtkcsstokenizer.c | 74 ++++++++++++++------------------ gtk/css/gtkcsstokenizerprivate.h | 15 ++++++- gtk/gtkcsscolorvalue.c | 2 +- gtk/gtkcssselector.c | 20 ++++----- 7 files changed, 72 insertions(+), 67 deletions(-) diff --git a/gdk/gdkrgba.c b/gdk/gdkrgba.c index 7732e507c8..9b52204038 100644 --- a/gdk/gdkrgba.c +++ b/gdk/gdkrgba.c @@ -586,7 +586,7 @@ gdk_rgba_parser_parse (GtkCssParser *parser, else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) || gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED)) { - const char *s = token->string.string; + const char *s = gtk_css_token_get_string (token); switch (strlen (s)) { @@ -637,13 +637,13 @@ gdk_rgba_parser_parse (GtkCssParser *parser, { *rgba = (GdkRGBA) { 0, 0, 0, 0 }; } - else if (gdk_rgba_parse (rgba, token->string.string)) + else if (gdk_rgba_parse (rgba, gtk_css_token_get_string (token))) { /* everything's fine */ } else { - gtk_css_parser_error_syntax (parser, "\"%s\" is not a valid color name.", token->string.string); + gtk_css_parser_error_syntax (parser, "\"%s\" is not a valid color name.", gtk_css_token_get_string (token)); return FALSE; } diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index 25943ec305..68069b477e 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -418,7 +418,7 @@ parse_string (GtkCssParser *parser, if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING)) return FALSE; - s = g_strdup (token->string.string); + s = g_strdup (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); g_free (*(char **) out_string); @@ -931,7 +931,7 @@ parse_declarations (GtkCssParser *parser, { if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)) gtk_css_parser_error_syntax (parser, "No variable named \"%s\"", - gtk_css_parser_get_token (parser)->string.string); + gtk_css_token_get_string (gtk_css_parser_get_token (parser))); else gtk_css_parser_error_syntax (parser, "Expected a variable name"); } @@ -1894,7 +1894,7 @@ parse_node (GtkCssParser *parser, if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)) gtk_css_parser_error_value (parser, "\"%s\" is not a valid node name", - gtk_css_parser_get_token (parser)->string.string); + gtk_css_token_get_string (gtk_css_parser_get_token (parser))); else gtk_css_parser_error_syntax (parser, "Expected a node name"); diff --git a/gtk/css/gtkcssparser.c b/gtk/css/gtkcssparser.c index 886e84f952..7b0cbcdaeb 100644 --- a/gtk/css/gtkcssparser.c +++ b/gtk/css/gtkcssparser.c @@ -648,7 +648,7 @@ gtk_css_parser_consume_function (GtkCssParser *self, token = gtk_css_parser_get_token (self); g_return_val_if_fail (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION), FALSE); - g_strlcpy (function_name, token->string.string, 64); + g_strlcpy (function_name, gtk_css_token_get_string (token), 64); gtk_css_parser_start_block (self); arg = 0; @@ -733,7 +733,7 @@ gtk_css_parser_has_ident (GtkCssParser *self, token = gtk_css_parser_get_token (self); return gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && - g_ascii_strcasecmp (token->string.string, ident) == 0; + g_ascii_strcasecmp (gtk_css_token_get_string (token), ident) == 0; } gboolean @@ -765,7 +765,7 @@ gtk_css_parser_has_function (GtkCssParser *self, token = gtk_css_parser_get_token (self); return gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION) && - g_ascii_strcasecmp (token->string.string, name) == 0; + g_ascii_strcasecmp (gtk_css_token_get_string (token), name) == 0; } /** @@ -818,7 +818,7 @@ gtk_css_parser_try_ident (GtkCssParser *self, token = gtk_css_parser_get_token (self); if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) || - g_ascii_strcasecmp (token->string.string, ident) != 0) + g_ascii_strcasecmp (gtk_css_token_get_string (token), ident) != 0) return FALSE; gtk_css_parser_consume_token (self); @@ -845,7 +845,7 @@ gtk_css_parser_try_at_keyword (GtkCssParser *self, token = gtk_css_parser_get_token (self); if (!gtk_css_token_is (token, GTK_CSS_TOKEN_AT_KEYWORD) || - g_ascii_strcasecmp (token->string.string, keyword) != 0) + g_ascii_strcasecmp (gtk_css_token_get_string (token), keyword) != 0) return FALSE; gtk_css_parser_consume_token (self); @@ -907,7 +907,7 @@ gtk_css_parser_consume_ident (GtkCssParser *self) return NULL; } - ident = g_strdup (token->string.string); + ident = g_strdup (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (self); return ident; @@ -938,7 +938,7 @@ gtk_css_parser_consume_string (GtkCssParser *self) return NULL; } - ident = g_strdup (token->string.string); + ident = g_strdup (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (self); return ident; @@ -979,7 +979,7 @@ gtk_css_parser_consume_url (GtkCssParser *self) if (gtk_css_token_is (token, GTK_CSS_TOKEN_URL)) { - url = g_strdup (token->string.string); + url = g_strdup (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (self); } else if (gtk_css_token_is_function (token, "url")) diff --git a/gtk/css/gtkcsstokenizer.c b/gtk/css/gtkcsstokenizer.c index 9cf59e1559..899221b5dc 100644 --- a/gtk/css/gtkcsstokenizer.c +++ b/gtk/css/gtkcsstokenizer.c @@ -50,7 +50,8 @@ gtk_css_token_clear (GtkCssToken *token) case GTK_CSS_TOKEN_HASH_UNRESTRICTED: case GTK_CSS_TOKEN_HASH_ID: case GTK_CSS_TOKEN_URL: - g_free (token->string.string); + if (token->string.len >= 16) + g_free (token->string.u.string); break; case GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION: @@ -294,7 +295,7 @@ gtk_css_token_is_ident (const GtkCssToken *token, const char *ident) { return gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) - && (g_ascii_strcasecmp (token->string.string, ident) == 0); + && (g_ascii_strcasecmp (gtk_css_token_get_string (token), ident) == 0); } gboolean @@ -302,7 +303,7 @@ gtk_css_token_is_function (const GtkCssToken *token, const char *ident) { return gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION) - && (g_ascii_strcasecmp (token->string.string, ident) == 0); + && (g_ascii_strcasecmp (gtk_css_token_get_string (token), ident) == 0); } gboolean @@ -322,33 +323,33 @@ gtk_css_token_print (const GtkCssToken *token, switch (token->type) { case GTK_CSS_TOKEN_STRING: - append_string (string, token->string.string); + append_string (string, gtk_css_token_get_string (token)); break; case GTK_CSS_TOKEN_IDENT: - append_ident (string, token->string.string); + append_ident (string, gtk_css_token_get_string (token)); break; case GTK_CSS_TOKEN_URL: g_string_append (string, "url("); - append_ident (string, token->string.string); + append_ident (string, gtk_css_token_get_string (token)); g_string_append (string, ")"); break; case GTK_CSS_TOKEN_FUNCTION: - append_ident (string, token->string.string); + append_ident (string, gtk_css_token_get_string (token)); g_string_append_c (string, '('); break; case GTK_CSS_TOKEN_AT_KEYWORD: g_string_append_c (string, '@'); - append_ident (string, token->string.string); + append_ident (string, gtk_css_token_get_string (token)); break; case GTK_CSS_TOKEN_HASH_UNRESTRICTED: case GTK_CSS_TOKEN_HASH_ID: g_string_append_c (string, '#'); - append_ident (string, token->string.string); + append_ident (string, gtk_css_token_get_string (token)); break; case GTK_CSS_TOKEN_DELIM: @@ -490,7 +491,7 @@ gtk_css_token_to_string (const GtkCssToken *token) static void gtk_css_token_init_string (GtkCssToken *token, GtkCssTokenType type, - char *string) + GString *string) { token->type = type; @@ -503,7 +504,11 @@ gtk_css_token_init_string (GtkCssToken *token, case GTK_CSS_TOKEN_HASH_UNRESTRICTED: case GTK_CSS_TOKEN_HASH_ID: case GTK_CSS_TOKEN_URL: - token->string.string = string; + token->string.len = string->len; + if (string->len < 16) + g_strlcpy (token->string.u.buf, string->str, 16); + else + token->string.u.string = g_strdup (string->str); break; default: g_assert_not_reached (); @@ -543,8 +548,7 @@ static void gtk_css_token_init_dimension (GtkCssToken *token, GtkCssTokenType type, double value, - const char *dimension, - int len) + GString *string) { token->type = type; @@ -555,13 +559,7 @@ gtk_css_token_init_dimension (GtkCssToken *token, case GTK_CSS_TOKEN_SIGNED_DIMENSION: case GTK_CSS_TOKEN_SIGNLESS_DIMENSION: token->dimension.value = value; - for (int i = 0; i < MIN (8, len); i++) - { - token->dimension.dimension[i] = dimension[i]; - if (dimension[i] == 0) - break; - } - token->dimension.dimension[7] = 0; + g_strlcpy (token->dimension.dimension, string->str, 8); break; default: g_assert_not_reached (); @@ -880,7 +878,7 @@ gtk_css_tokenizer_read_escape (GtkCssTokenizer *tokenizer) return value; } -static char * +static void gtk_css_tokenizer_read_name (GtkCssTokenizer *tokenizer) { g_string_set_size (tokenizer->name_buffer, 0); @@ -916,8 +914,6 @@ gtk_css_tokenizer_read_name (GtkCssTokenizer *tokenizer) } } while (tokenizer->data != tokenizer->end); - - return g_strndup (tokenizer->name_buffer->str, tokenizer->name_buffer->len); } static void @@ -1010,7 +1006,8 @@ gtk_css_tokenizer_read_url (GtkCssTokenizer *tokenizer, } } - gtk_css_token_init_string (token, GTK_CSS_TOKEN_URL, g_string_free (url, FALSE)); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_URL, url); + g_string_free (url, TRUE); return TRUE; } @@ -1020,12 +1017,12 @@ gtk_css_tokenizer_read_ident_like (GtkCssTokenizer *tokenizer, GtkCssToken *token, GError **error) { - char *name = gtk_css_tokenizer_read_name (tokenizer); + gtk_css_tokenizer_read_name (tokenizer); if (*tokenizer->data == '(') { gtk_css_tokenizer_consume_ascii (tokenizer); - if (g_ascii_strcasecmp (name, "url") == 0) + if (g_ascii_strcasecmp (tokenizer->name_buffer->str, "url") == 0) { const char *data = tokenizer->data; @@ -1033,18 +1030,15 @@ gtk_css_tokenizer_read_ident_like (GtkCssTokenizer *tokenizer, data++; if (*data != '"' && *data != '\'') - { - g_free (name); - return gtk_css_tokenizer_read_url (tokenizer, token, error); - } + return gtk_css_tokenizer_read_url (tokenizer, token, error); } - gtk_css_token_init_string (token, GTK_CSS_TOKEN_FUNCTION, name); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_FUNCTION, tokenizer->name_buffer); return TRUE; } else { - gtk_css_token_init_string (token, GTK_CSS_TOKEN_IDENT, name); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_IDENT, tokenizer->name_buffer); return TRUE; } } @@ -1134,8 +1128,8 @@ gtk_css_tokenizer_read_numeric (GtkCssTokenizer *tokenizer, else type = has_sign ? GTK_CSS_TOKEN_SIGNED_DIMENSION : GTK_CSS_TOKEN_SIGNLESS_DIMENSION; - char *name = gtk_css_tokenizer_read_name (tokenizer); - gtk_css_token_init_dimension (token, type, value, name, strlen (name)); + gtk_css_tokenizer_read_name (tokenizer); + gtk_css_token_init_dimension (token, type, value, tokenizer->name_buffer); } else if (gtk_css_tokenizer_remaining (tokenizer) > 0 && *tokenizer->data == '%') { @@ -1244,7 +1238,7 @@ gtk_css_tokenizer_read_string (GtkCssTokenizer *tokenizer, } } - gtk_css_token_init_string (token, GTK_CSS_TOKEN_STRING, g_strdup (tokenizer->name_buffer->str)); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_STRING, tokenizer->name_buffer); return TRUE; } @@ -1328,9 +1322,8 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, else type = GTK_CSS_TOKEN_HASH_UNRESTRICTED; - gtk_css_token_init_string (token, - type, - gtk_css_tokenizer_read_name (tokenizer)); + gtk_css_tokenizer_read_name (tokenizer); + gtk_css_token_init_string (token, type, tokenizer->name_buffer); } else { @@ -1410,9 +1403,8 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, gtk_css_tokenizer_consume_ascii (tokenizer); if (gtk_css_tokenizer_has_identifier (tokenizer)) { - gtk_css_token_init_string (token, - GTK_CSS_TOKEN_AT_KEYWORD, - gtk_css_tokenizer_read_name (tokenizer)); + gtk_css_tokenizer_read_name (tokenizer); + gtk_css_token_init_string (token, GTK_CSS_TOKEN_AT_KEYWORD, tokenizer->name_buffer); } else { diff --git a/gtk/css/gtkcsstokenizerprivate.h b/gtk/css/gtkcsstokenizerprivate.h index 6f97bd904e..6f4df9c22e 100644 --- a/gtk/css/gtkcsstokenizerprivate.h +++ b/gtk/css/gtkcsstokenizerprivate.h @@ -81,7 +81,11 @@ typedef struct _GtkCssDimensionToken GtkCssDimensionToken; struct _GtkCssStringToken { GtkCssTokenType type; - char *string; + int len; + union { + char buf[16]; + char *string; + } u; }; struct _GtkCssDelimToken { @@ -108,6 +112,15 @@ union _GtkCssToken { GtkCssDimensionToken dimension; }; +static inline const char * +gtk_css_token_get_string (const GtkCssToken *token) +{ + if (token->string.len < 16) + return token->string.u.buf; + else + return token->string.u.string; +} + void gtk_css_token_clear (GtkCssToken *token); gboolean gtk_css_token_is_finite (const GtkCssToken *token) G_GNUC_PURE; diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c index 4b0b4adfe4..b326b9cae9 100644 --- a/gtk/gtkcsscolorvalue.c +++ b/gtk/gtkcsscolorvalue.c @@ -722,7 +722,7 @@ _gtk_css_color_value_parse (GtkCssParser *parser) { const GtkCssToken *token = gtk_css_parser_get_token (parser); - value = _gtk_css_color_value_new_name (token->string.string); + value = _gtk_css_color_value_new_name (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); return value; diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c index 207d83ac7d..baed35dadb 100644 --- a/gtk/gtkcssselector.c +++ b/gtk/gtkcssselector.c @@ -947,7 +947,7 @@ gtk_css_selector_parse_selector_class (GtkCssParser *parser, selector = gtk_css_selector_new (negate ? >K_CSS_SELECTOR_NOT_CLASS : >K_CSS_SELECTOR_CLASS, selector); - selector->style_class.style_class = g_quark_from_string (token->string.string); + selector->style_class.style_class = g_quark_from_string (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); return selector; } @@ -1060,7 +1060,7 @@ parse_n_plus_b (GtkCssParser *parser, return parse_plus_b (parser, TRUE, b); } else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && - string_has_number (token->string.string, "n-", b)) + string_has_number (gtk_css_token_get_string (token), "n-", b)) { *a = before; *b = -*b; @@ -1156,7 +1156,7 @@ parse_a_n_plus_b (GtkCssParser *parser, } else if (!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && - string_has_number (token->string.string, "-n-", b)) + string_has_number (gtk_css_token_get_string (token), "-n-", b)) { *a = -1; *b = -*b; @@ -1169,7 +1169,7 @@ parse_a_n_plus_b (GtkCssParser *parser, return parse_n_plus_b (parser, seen_sign ? seen_sign : 1, a, b); } else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && - string_has_number (token->string.string, "n-", b)) + string_has_number (gtk_css_token_get_string (token), "n-", b)) { *a = seen_sign ? seen_sign : 1; *b = -*b; @@ -1177,7 +1177,7 @@ parse_a_n_plus_b (GtkCssParser *parser, return TRUE; } else if (!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && - string_has_number (token->string.string, "-n-", b)) + string_has_number (gtk_css_token_get_string (token), "-n-", b)) { *a = -1; *b = -*b; @@ -1288,7 +1288,7 @@ gtk_css_selector_parse_selector_pseudo_class (GtkCssParser *parser, for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++) { - if (g_ascii_strcasecmp (pseudo_classes[i].name, token->string.string) == 0) + if (g_ascii_strcasecmp (pseudo_classes[i].name, gtk_css_token_get_string (token)) == 0) { if (pseudo_classes[i].state_flag) { @@ -1380,13 +1380,13 @@ gtk_css_selector_parse_selector_pseudo_class (GtkCssParser *parser, else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT)) { selector = gtk_css_selector_new (>K_CSS_SELECTOR_NOT_NAME, selector); - selector->name.name = g_quark_from_string (token->string.string); + selector->name.name = g_quark_from_string (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); } else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID)) { selector = gtk_css_selector_new (>K_CSS_SELECTOR_NOT_ID, selector); - selector->id.name = g_quark_from_string (token->string.string); + selector->id.name = g_quark_from_string (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); } else if (gtk_css_token_is_delim (token, '.')) @@ -1499,13 +1499,13 @@ gtk_css_selector_parse_simple_selector (GtkCssParser *parser, else if (!parsed_something && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT)) { selector = gtk_css_selector_new (>K_CSS_SELECTOR_NAME, selector); - selector->name.name = g_quark_from_string (token->string.string); + selector->name.name = g_quark_from_string (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); } else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID)) { selector = gtk_css_selector_new (>K_CSS_SELECTOR_ID, selector); - selector->id.name = g_quark_from_string (token->string.string); + selector->id.name = g_quark_from_string (gtk_css_token_get_string (token)); gtk_css_parser_consume_token (parser); } else if (gtk_css_token_is_delim (token, '.')) From d226dc3812207d80fc62d715cdbdf3cc3926b395 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 12 Jan 2023 00:35:43 -0500 Subject: [PATCH 8/8] iconcache: Be a bit less wasteful --- gtk/gtkiconcache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/gtk/gtkiconcache.c b/gtk/gtkiconcache.c index 706de5450d..d6ecd4f2b0 100644 --- a/gtk/gtkiconcache.c +++ b/gtk/gtkiconcache.c @@ -188,6 +188,7 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache, guint32 image_list_offset, n_images; int i, j; GHashTable *icons = NULL; + GString *string; directory_index = get_directory_index (cache, directory); @@ -197,6 +198,8 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache, hash_offset = GET_UINT32 (cache->buffer, 4); n_buckets = GET_UINT32 (cache->buffer, hash_offset); + string = g_string_new (""); + for (i = 0; i < n_buckets; i++) { chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * i); @@ -223,15 +226,18 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache, const char *name = cache->buffer + name_offset; const char *interned_name; guint32 hash_flags = 0; + int len; /* Icons named foo.symbolic.png are stored in the cache as "foo.symbolic" with ICON_CACHE_FLAG_PNG, * but we convert it internally to ICON_CACHE_FLAG_SYMBOLIC_PNG. * Otherwise we use the same enum values and names as on disk. */ - if (g_str_has_suffix (name, ".symbolic") && (flags & ICON_CACHE_FLAG_PNG_SUFFIX) != 0) + + len = strlen (name); + if (g_str_equal (name + len - strlen (".symbolic"), ".symbolic") && (flags & ICON_CACHE_FLAG_PNG_SUFFIX) != 0) { - char *converted_name = g_strndup (name, strlen (name) - 9); - interned_name = gtk_string_set_add (set, converted_name); - g_free (converted_name); + g_string_set_size (string, 0); + g_string_append_len (string, name, len - strlen (".symbolic")); + interned_name = gtk_string_set_add (set, string->str); flags |= ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX; flags &= ~ICON_CACHE_FLAG_PNG_SUFFIX; } @@ -249,5 +255,7 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache, } } + g_string_free (string, TRUE); + return icons; }