diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 3b7cc28e7a5581fe5f3a778953977e42c79ec7e5..f7efd2bf413cd3f320efb011ce638f710a372ef9 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -1621,6 +1621,7 @@ g_desktop_app_info_set_desktop_env g_desktop_app_info_get_string g_desktop_app_info_get_locale_string g_desktop_app_info_get_boolean +g_desktop_app_info_get_string_list g_desktop_app_info_has_key GDesktopAppLaunchCallback g_desktop_app_info_launch_uris_as_manager diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index d0ffbace3e0bcfa3283173443daedbb882d3d6e9..c55a0abe29912aade16be8ab88b55794f2075f2d 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -4534,6 +4534,33 @@ g_desktop_app_info_get_boolean (GDesktopAppInfo *info, G_KEY_FILE_DESKTOP_GROUP, key, NULL); } +/** + * g_desktop_app_info_get_string_list: + * @info: a #GDesktopAppInfo + * @key: the key to look up + * @length: (out) (optional): return location for the number of returned strings, or %NULL + * + * Looks up a string list value in the keyfile backing @info. + * + * The @key is looked up in the "Desktop Entry" group. + * + * Returns: (array zero-terminated=1 length=length) (element-type utf8) (transfer full): + * a %NULL-terminated string array or %NULL if the specified + * key cannot be found. The array should be freed with g_strfreev(). + * + * Since: 2.59.0 + */ +gchar ** +g_desktop_app_info_get_string_list (GDesktopAppInfo *info, + const char *key, + gsize *length) +{ + g_return_val_if_fail (G_IS_DESKTOP_APP_INFO (info), NULL); + + return g_key_file_get_string_list (info->keyfile, + G_KEY_FILE_DESKTOP_GROUP, key, length, NULL); +} + /** * g_desktop_app_info_has_key: * @info: a #GDesktopAppInfo diff --git a/gio/gdesktopappinfo.h b/gio/gdesktopappinfo.h index 86a3caa309944a755191d7c719cbde8d9c0fb9c8..1254038a48d18093501b148ca4eb57a3cc423687 100644 --- a/gio/gdesktopappinfo.h +++ b/gio/gdesktopappinfo.h @@ -89,6 +89,11 @@ GLIB_AVAILABLE_IN_2_36 gboolean g_desktop_app_info_get_boolean (GDesktopAppInfo *info, const char *key); +GLIB_AVAILABLE_IN_2_60 +gchar ** g_desktop_app_info_get_string_list (GDesktopAppInfo *info, + const char *key, + gsize *length); + GLIB_AVAILABLE_IN_2_38 const gchar * const * g_desktop_app_info_list_actions (GDesktopAppInfo *info); diff --git a/gio/tests/appinfo.c b/gio/tests/appinfo.c index a52bc7094048d50d63d88026aa92687feb3c9eb6..e75c4abe710c8cf0a09bcf71b065f14641fcfeb9 100644 --- a/gio/tests/appinfo.c +++ b/gio/tests/appinfo.c @@ -512,6 +512,8 @@ test_from_keyfile (void) GKeyFile *kf; GError *error = NULL; const gchar *categories; + gchar **categories_list; + gsize categories_count; gchar **keywords; const gchar *file; const gchar *name; @@ -522,7 +524,7 @@ test_from_keyfile (void) g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error); g_assert_no_error (error); info = g_desktop_app_info_new_from_keyfile (kf); - g_key_file_free (kf); + g_key_file_unref (kf); g_assert (info != NULL); g_object_get (info, "filename", &file, NULL); @@ -532,6 +534,11 @@ test_from_keyfile (void) g_assert (file == NULL); categories = g_desktop_app_info_get_categories (info); g_assert_cmpstr (categories, ==, "GNOME;GTK;"); + categories_list = g_desktop_app_info_get_string_list (info, "Categories", &categories_count); + g_assert_cmpint (categories_count, ==, 2); + g_assert_cmpint (g_strv_length (categories_list), ==, 2); + g_assert_cmpstr (categories_list[0], ==, "GNOME"); + g_assert_cmpstr (categories_list[1], ==, "GTK"); keywords = (gchar **)g_desktop_app_info_get_keywords (info); g_assert_cmpint (g_strv_length (keywords), ==, 2); g_assert_cmpstr (keywords[0], ==, "keyword1"); @@ -540,6 +547,7 @@ test_from_keyfile (void) g_assert_cmpstr (name, ==, "generic-appinfo-test"); g_assert (!g_desktop_app_info_get_nodisplay (info)); + g_strfreev (categories_list); g_object_unref (info); } diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index ae3bbbc1d5726f27ca5af898db4189b5ad9fbab9..4e9b53541f15db6c5798b1e1550d7732abad4cdc 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -1191,7 +1191,11 @@ g_key_file_free (GKeyFile *key_file) g_return_if_fail (key_file != NULL); g_key_file_clear (key_file); - g_key_file_unref (key_file); + + if (g_atomic_int_dec_and_test (&key_file->ref_count)) + g_slice_free (GKeyFile, key_file); + else + g_key_file_init (key_file); } /** diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c index 16f3b788b1e6761b6d28c027dab06a5ec8aeb138..9ee7d02c4830856148d996f963920b91af66e7c0 100644 --- a/glib/tests/keyfile.c +++ b/glib/tests/keyfile.c @@ -1726,6 +1726,42 @@ test_get_locale (void) g_key_file_free (kf); } +static void +test_free_when_not_last_ref (void) +{ + GKeyFile *kf; + GError *error = NULL; + const gchar *data = + "[Group]\n" + "Key=Value\n"; + + kf = load_data (data, G_KEY_FILE_NONE); + /* Add a second ref */ + g_key_file_ref (kf); + + /* Quick coherence check */ + g_assert_true (g_key_file_has_group (kf, "Group")); + g_assert_true (g_key_file_has_key (kf, "Group", "Key", &error)); + g_assert_no_error (error); + + /* Should clear all keys and groups, and remove one ref */ + g_key_file_free (kf); + + /* kf should still work */ + g_assert_false (g_key_file_has_group (kf, "Group")); + g_assert_false (g_key_file_has_key (kf, "Group", "Key", &error)); + check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); + g_clear_error (&error); + + g_key_file_load_from_data (kf, data, -1, G_KEY_FILE_NONE, &error); + g_assert_no_error (error); + + g_assert_true (g_key_file_has_group (kf, "Group")); + g_assert_true (g_key_file_has_key (kf, "Group", "Key", &error)); + + g_key_file_unref (kf); +} + int main (int argc, char *argv[]) { @@ -1771,6 +1807,7 @@ main (int argc, char *argv[]) g_test_add_func ("/keyfile/roundtrip", test_roundtrip); g_test_add_func ("/keyfile/bytes", test_bytes); g_test_add_func ("/keyfile/get-locale", test_get_locale); + g_test_add_func ("/keyfile/free-when-not-last-ref", test_free_when_not_last_ref); return g_test_run (); }