mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	Add g_variant_lookup() and tests
Convenience API for doing lookups in dictionaries where the key is a string or object path.
This commit is contained in:
		| @@ -3015,6 +3015,8 @@ g_variant_get_maybe | ||||
| g_variant_n_children | ||||
| g_variant_get_child_value | ||||
| g_variant_get_child | ||||
| g_variant_lookup_value | ||||
| g_variant_lookup | ||||
| g_variant_get_fixed_array | ||||
|  | ||||
| <SUBSECTION> | ||||
|   | ||||
| @@ -1880,6 +1880,8 @@ g_variant_get | ||||
|  | ||||
| g_variant_builder_add | ||||
| g_variant_get_child | ||||
| g_variant_lookup_value | ||||
| g_variant_lookup | ||||
| g_variant_iter_next | ||||
| g_variant_iter_loop | ||||
|  | ||||
|   | ||||
							
								
								
									
										144
									
								
								glib/gvariant.c
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								glib/gvariant.c
									
									
									
									
									
								
							| @@ -898,6 +898,150 @@ g_variant_new_dict_entry (GVariant *key, | ||||
|   return value; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_variant_lookup: | ||||
|  * @dictionary: a dictionary #GVariant | ||||
|  * @key: the key to lookup in the dictionary | ||||
|  * @format_string: a GVariant format string | ||||
|  * @...: the arguments to unpack the value into | ||||
|  * | ||||
|  * Looks up a value in a dictionary #GVariant. | ||||
|  * | ||||
|  * This function is a wrapper around g_variant_lookup_value() and | ||||
|  * g_variant_get().  In the case that %NULL would have been returned, | ||||
|  * this function returns %FALSE.  Otherwise, it unpacks the returned | ||||
|  * value and returns %TRUE. | ||||
|  * | ||||
|  * See g_variant_get() for information about @format_string. | ||||
|  * | ||||
|  * Returns: %TRUE if a value was unpacked | ||||
|  * | ||||
|  * Since: 2.28 | ||||
|  */ | ||||
| gboolean | ||||
| g_variant_lookup (GVariant    *dictionary, | ||||
|                   const gchar *key, | ||||
|                   const gchar *format_string, | ||||
|                   ...) | ||||
| { | ||||
|   GVariantType *type; | ||||
|   GVariant *value; | ||||
|  | ||||
|   /* flatten */ | ||||
|   g_variant_get_data (dictionary); | ||||
|  | ||||
|   type = g_variant_format_string_scan_type (format_string, NULL, NULL); | ||||
|   value = g_variant_lookup_value (dictionary, key, type); | ||||
|   g_variant_type_free (type); | ||||
|  | ||||
|   if (value) | ||||
|     { | ||||
|       va_list ap; | ||||
|  | ||||
|       va_start (ap, format_string); | ||||
|       g_variant_get_va (value, format_string, NULL, &ap); | ||||
|       g_variant_unref (value); | ||||
|       va_end (ap); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_variant_lookup: | ||||
|  * @dictionary: a dictionary #GVariant | ||||
|  * @key: the key to lookup in the dictionary | ||||
|  * @expected_type: a #GVariantType, or %NULL | ||||
|  * | ||||
|  * Looks up a value in a dictionary #GVariant. | ||||
|  * | ||||
|  * This function works with dictionaries of the type | ||||
|  * <literal>a{s*}</literal> (and equally well with type | ||||
|  * <literal>a{o*}</literal>, but we only further discuss the string case | ||||
|  * for sake of clarity). | ||||
|  * | ||||
|  * In the event that @dictionary has the type <literal>a{sv}</literal>, | ||||
|  * the @expected_type string specifies what type of value is expected to | ||||
|  * be inside of the variant.  If the value inside the variant has a | ||||
|  * different type then %NULL is returned.  In the event that @dictionary | ||||
|  * has a value type other than <literal>v</literal> then @expected_type | ||||
|  * must directly match the key type and it is used to unpack the value | ||||
|  * directly or an error occurs. | ||||
|  * | ||||
|  * In either case, if @key is not found in @dictionary, %NULL is | ||||
|  * returned. | ||||
|  * | ||||
|  * If the key is found and the value has the correct type, it is | ||||
|  * returned.  If @expected_type was specified then any non-%NULL return | ||||
|  * value will have this type. | ||||
|  * | ||||
|  * Returns: the value of the dictionary key, or %NULL | ||||
|  * | ||||
|  * Since: 2.28 | ||||
|  */ | ||||
| GVariant * | ||||
| g_variant_lookup_value (GVariant           *dictionary, | ||||
|                         const gchar        *key, | ||||
|                         const GVariantType *expected_type) | ||||
| { | ||||
|   GVariantIter iter; | ||||
|   GVariant *entry; | ||||
|   GVariant *value; | ||||
|  | ||||
|   g_return_val_if_fail (g_variant_is_of_type (dictionary, | ||||
|                                               G_VARIANT_TYPE ("a{s*}")) || | ||||
|                         g_variant_is_of_type (dictionary, | ||||
|                                               G_VARIANT_TYPE ("a{o*}")), | ||||
|                         NULL); | ||||
|  | ||||
|   g_variant_iter_init (&iter, dictionary); | ||||
|  | ||||
|   while ((entry = g_variant_iter_next_value (&iter))) | ||||
|     { | ||||
|       GVariant *entry_key; | ||||
|       gboolean matches; | ||||
|  | ||||
|       entry_key = g_variant_get_child_value (entry, 0); | ||||
|       matches = strcmp (g_variant_get_string (entry_key, NULL), key) == 0; | ||||
|       g_variant_unref (entry_key); | ||||
|  | ||||
|       if (matches) | ||||
|         break; | ||||
|  | ||||
|       g_variant_unref (entry); | ||||
|     } | ||||
|  | ||||
|   if (entry == NULL) | ||||
|     return NULL; | ||||
|  | ||||
|   value = g_variant_get_child_value (entry, 1); | ||||
|   g_variant_unref (entry); | ||||
|  | ||||
|   if (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT)) | ||||
|     { | ||||
|       GVariant *tmp; | ||||
|  | ||||
|       tmp = g_variant_get_variant (value); | ||||
|       g_variant_unref (value); | ||||
|  | ||||
|       if (expected_type && !g_variant_is_of_type (tmp, expected_type)) | ||||
|         { | ||||
|           g_variant_unref (tmp); | ||||
|           tmp = NULL; | ||||
|         } | ||||
|  | ||||
|       value = tmp; | ||||
|     } | ||||
|  | ||||
|   g_return_val_if_fail (expected_type == NULL || value == NULL || | ||||
|                         g_variant_is_of_type (value, expected_type), NULL); | ||||
|  | ||||
|   return value; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_variant_get_fixed_array: | ||||
|  * @value: a #GVariant array with fixed-sized elements | ||||
|   | ||||
| @@ -134,6 +134,13 @@ void                            g_variant_get_child                     (GVarian | ||||
|                                                                          ...); | ||||
| GVariant *                      g_variant_get_child_value               (GVariant             *value, | ||||
|                                                                          gsize                 index_); | ||||
| gboolean                        g_variant_lookup                        (GVariant             *value, | ||||
|                                                                          const gchar          *key, | ||||
|                                                                          const gchar          *format_string, | ||||
|                                                                          ...); | ||||
| GVariant *                      g_variant_lookup_value                  (GVariant             *value, | ||||
|                                                                          const gchar          *key, | ||||
|                                                                          const GVariantType   *type); | ||||
| gconstpointer                   g_variant_get_fixed_array               (GVariant             *value, | ||||
|                                                                          gsize                *n_elements, | ||||
|                                                                          gsize                 element_size); | ||||
|   | ||||
| @@ -3897,6 +3897,78 @@ test_bytestring (void) | ||||
|   g_variant_unref (untrusted_empty); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_lookup_value (void) | ||||
| { | ||||
|   struct { | ||||
|     const gchar *dict, *key, *value; | ||||
|   } cases[] = { | ||||
|     { "@a{ss} {'x':  'y'}",   "x",  "'y'" }, | ||||
|     { "@a{ss} {'x':  'y'}",   "y"         }, | ||||
|     { "@a{os} {'/x': 'y'}",   "/x", "'y'" }, | ||||
|     { "@a{os} {'/x': 'y'}",   "/y"        }, | ||||
|     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" }, | ||||
|     { "@a{sv} {'x':  <5>}",   "x",  "5"   }, | ||||
|     { "@a{sv} {'x':  <'y'>}", "y"         } | ||||
|   }; | ||||
|   gint i; | ||||
|  | ||||
|   for (i = 0; i < G_N_ELEMENTS (cases); i++) | ||||
|     { | ||||
|       GVariant *dictionary; | ||||
|       GVariant *value; | ||||
|       gchar *p; | ||||
|        | ||||
|       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL); | ||||
|       value = g_variant_lookup_value (dictionary, cases[i].key, NULL); | ||||
|       g_variant_unref (dictionary); | ||||
|  | ||||
|       if (value == NULL && cases[i].value == NULL) | ||||
|         continue; | ||||
|  | ||||
|       g_assert (value && cases[i].value); | ||||
|       p = g_variant_print (value, FALSE); | ||||
|       g_assert_cmpstr (cases[i].value, ==, p); | ||||
|       g_variant_unref (value); | ||||
|       g_free (p); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_lookup (void) | ||||
| { | ||||
|   const gchar *str; | ||||
|   GVariant *dict; | ||||
|   gboolean ok; | ||||
|   gint num; | ||||
|  | ||||
|   dict = g_variant_parse (NULL, | ||||
|                           "{'a': <5>, 'b': <'c'>}", | ||||
|                           NULL, NULL, NULL); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "a", "i", &num); | ||||
|   g_assert (ok); | ||||
|   g_assert_cmpint (num, ==, 5); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "a", "&s", &str); | ||||
|   g_assert (!ok); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "q", "&s", &str); | ||||
|   g_assert (!ok); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "b", "i", &num); | ||||
|   g_assert (!ok); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "b", "&s", &str); | ||||
|   g_assert (ok); | ||||
|   g_assert_cmpstr (str, ==, "c"); | ||||
|  | ||||
|   ok = g_variant_lookup (dict, "q", "&s", &str); | ||||
|   g_assert (!ok); | ||||
|  | ||||
|   g_variant_unref (dict); | ||||
| } | ||||
|  | ||||
| int | ||||
| main (int argc, char **argv) | ||||
| { | ||||
| @@ -3937,6 +4009,8 @@ main (int argc, char **argv) | ||||
|   g_test_add_func ("/gvariant/parse-positional", test_parse_positional); | ||||
|   g_test_add_func ("/gvariant/floating", test_floating); | ||||
|   g_test_add_func ("/gvariant/bytestring", test_bytestring); | ||||
|   g_test_add_func ("/gvariant/lookup-value", test_lookup_value); | ||||
|   g_test_add_func ("/gvariant/lookup", test_lookup); | ||||
|  | ||||
|   return g_test_run (); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user