summaryrefslogtreecommitdiffstats
path: root/libgimpconfig/gimpconfig-iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgimpconfig/gimpconfig-iface.c')
-rw-r--r--libgimpconfig/gimpconfig-iface.c859
1 files changed, 859 insertions, 0 deletions
diff --git a/libgimpconfig/gimpconfig-iface.c b/libgimpconfig/gimpconfig-iface.c
new file mode 100644
index 0000000..6604aca
--- /dev/null
+++ b/libgimpconfig/gimpconfig-iface.c
@@ -0,0 +1,859 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * Config file serialization and deserialization interface
+ * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org>
+ *
+ * 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 3 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
+ * Library 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
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gio/gio.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "gimpconfigtypes.h"
+
+#include "gimpconfigwriter.h"
+#include "gimpconfig-iface.h"
+#include "gimpconfig-deserialize.h"
+#include "gimpconfig-serialize.h"
+#include "gimpconfig-params.h"
+#include "gimpconfig-utils.h"
+#include "gimpscanner.h"
+
+#include "libgimp/libgimp-intl.h"
+
+
+/**
+ * SECTION: gimpconfig-iface
+ * @title: GimpConfig-iface
+ * @short_description: High-level API for libgimpconfig.
+ *
+ * High-level API for libgimpconfig.
+ **/
+
+
+/*
+ * The GimpConfig serialization and deserialization interface.
+ */
+
+
+/* local function prototypes */
+
+static void gimp_config_iface_default_init (GimpConfigInterface *iface);
+static void gimp_config_iface_base_init (GimpConfigInterface *iface);
+
+static gboolean gimp_config_iface_serialize (GimpConfig *config,
+ GimpConfigWriter *writer,
+ gpointer data);
+static gboolean gimp_config_iface_deserialize (GimpConfig *config,
+ GScanner *scanner,
+ gint nest_level,
+ gpointer data);
+static GimpConfig * gimp_config_iface_duplicate (GimpConfig *config);
+static gboolean gimp_config_iface_equal (GimpConfig *a,
+ GimpConfig *b);
+static void gimp_config_iface_reset (GimpConfig *config);
+static gboolean gimp_config_iface_copy (GimpConfig *src,
+ GimpConfig *dest,
+ GParamFlags flags);
+
+
+/* private functions */
+
+
+GType
+gimp_config_get_type (void)
+{
+ static GType config_iface_type = 0;
+
+ if (! config_iface_type)
+ {
+ const GTypeInfo config_iface_info =
+ {
+ sizeof (GimpConfigInterface),
+ (GBaseInitFunc) gimp_config_iface_base_init,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gimp_config_iface_default_init,
+ (GClassFinalizeFunc) NULL,
+ };
+
+ config_iface_type = g_type_register_static (G_TYPE_INTERFACE,
+ "GimpConfigInterface",
+ &config_iface_info,
+ 0);
+
+ g_type_interface_add_prerequisite (config_iface_type, G_TYPE_OBJECT);
+ }
+
+ return config_iface_type;
+}
+
+GType
+gimp_config_interface_get_type (void)
+{
+ return gimp_config_get_type ();
+}
+
+static void
+gimp_config_iface_default_init (GimpConfigInterface *iface)
+{
+ iface->serialize = gimp_config_iface_serialize;
+ iface->deserialize = gimp_config_iface_deserialize;
+ iface->duplicate = gimp_config_iface_duplicate;
+ iface->equal = gimp_config_iface_equal;
+ iface->reset = gimp_config_iface_reset;
+ iface->copy = gimp_config_iface_copy;
+}
+
+static void
+gimp_config_iface_base_init (GimpConfigInterface *iface)
+{
+ /* always set these to NULL since we don't want to inherit them
+ * from parent classes
+ */
+ iface->serialize_property = NULL;
+ iface->deserialize_property = NULL;
+}
+
+static gboolean
+gimp_config_iface_serialize (GimpConfig *config,
+ GimpConfigWriter *writer,
+ gpointer data)
+{
+ return gimp_config_serialize_properties (config, writer);
+}
+
+static gboolean
+gimp_config_iface_deserialize (GimpConfig *config,
+ GScanner *scanner,
+ gint nest_level,
+ gpointer data)
+{
+ return gimp_config_deserialize_properties (config, scanner, nest_level);
+}
+
+static GimpConfig *
+gimp_config_iface_duplicate (GimpConfig *config)
+{
+ GObject *object = G_OBJECT (config);
+ GObjectClass *klass = G_OBJECT_GET_CLASS (object);
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ gint n_construct_properties = 0;
+ const gchar **construct_names = NULL;
+ GValue *construct_values = NULL;
+ guint i;
+ GObject *dup;
+
+ property_specs = g_object_class_list_properties (klass, &n_property_specs);
+
+ construct_names = g_new0 (const gchar *, n_property_specs);
+ construct_values = g_new0 (GValue, n_property_specs);
+
+ for (i = 0; i < n_property_specs; i++)
+ {
+ GParamSpec *prop_spec = property_specs[i];
+
+ if ((prop_spec->flags & G_PARAM_READABLE) &&
+ (prop_spec->flags & G_PARAM_WRITABLE) &&
+ (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY))
+ {
+ construct_names[n_construct_properties] = prop_spec->name;
+
+ g_value_init (&construct_values[n_construct_properties],
+ prop_spec->value_type);
+ g_object_get_property (object, prop_spec->name,
+ &construct_values[n_construct_properties]);
+
+ n_construct_properties++;
+ }
+ }
+
+ g_free (property_specs);
+
+ dup = g_object_new_with_properties (G_TYPE_FROM_INSTANCE (object),
+ n_construct_properties,
+ (const gchar **) construct_names,
+ (const GValue *) construct_values);
+
+ for (i = 0; i < n_construct_properties; i++)
+ g_value_unset (&construct_values[i]);
+
+ g_free (construct_names);
+ g_free (construct_values);
+
+ gimp_config_copy (config, GIMP_CONFIG (dup), 0);
+
+ return GIMP_CONFIG (dup);
+}
+
+static gboolean
+gimp_config_iface_equal (GimpConfig *a,
+ GimpConfig *b)
+{
+ GObjectClass *klass;
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ guint i;
+ gboolean equal = TRUE;
+
+ klass = G_OBJECT_GET_CLASS (a);
+
+ property_specs = g_object_class_list_properties (klass, &n_property_specs);
+
+ for (i = 0; equal && i < n_property_specs; i++)
+ {
+ GParamSpec *prop_spec;
+ GValue a_value = G_VALUE_INIT;
+ GValue b_value = G_VALUE_INIT;
+
+ prop_spec = property_specs[i];
+
+ if (! (prop_spec->flags & G_PARAM_READABLE))
+ continue;
+
+ g_value_init (&a_value, prop_spec->value_type);
+ g_value_init (&b_value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
+ g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
+
+ if (g_param_values_cmp (prop_spec, &a_value, &b_value))
+ {
+ if ((prop_spec->flags & GIMP_CONFIG_PARAM_AGGREGATE) &&
+ G_IS_PARAM_SPEC_OBJECT (prop_spec) &&
+ g_type_interface_peek (g_type_class_peek (prop_spec->value_type),
+ GIMP_TYPE_CONFIG))
+ {
+ if (! gimp_config_is_equal_to (g_value_get_object (&a_value),
+ g_value_get_object (&b_value)))
+ {
+ equal = FALSE;
+ }
+ }
+ else
+ {
+ equal = FALSE;
+ }
+ }
+
+ g_value_unset (&a_value);
+ g_value_unset (&b_value);
+ }
+
+ g_free (property_specs);
+
+ return equal;
+}
+
+static void
+gimp_config_iface_reset (GimpConfig *config)
+{
+ gimp_config_reset_properties (G_OBJECT (config));
+}
+
+static gboolean
+gimp_config_iface_copy (GimpConfig *src,
+ GimpConfig *dest,
+ GParamFlags flags)
+{
+ return gimp_config_sync (G_OBJECT (src), G_OBJECT (dest), flags);
+}
+
+
+/* public functions */
+
+
+/**
+ * gimp_config_serialize_to_file:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @filename: the name of the file to write the configuration to.
+ * @header: optional file header (must be ASCII only)
+ * @footer: optional file footer (must be ASCII only)
+ * @data: user data passed to the serialize implementation.
+ * @error: return location for a possible error
+ *
+ * Serializes the object properties of @config to the file specified
+ * by @filename. If a file with that name already exists, it is
+ * overwritten. Basically this function opens @filename for you and
+ * calls the serialize function of the @config's #GimpConfigInterface.
+ *
+ * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_serialize_to_file (GimpConfig *config,
+ const gchar *filename,
+ const gchar *header,
+ const gchar *footer,
+ gpointer data,
+ GError **error)
+{
+ GimpConfigWriter *writer;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ writer = gimp_config_writer_new_file (filename, TRUE, header, error);
+ if (!writer)
+ return FALSE;
+
+ GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
+
+ return gimp_config_writer_finish (writer, footer, error);
+}
+
+/**
+ * gimp_config_serialize_to_gfile:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @file: the #GFile to write the configuration to.
+ * @header: optional file header (must be ASCII only)
+ * @footer: optional file footer (must be ASCII only)
+ * @data: user data passed to the serialize implementation.
+ * @error: return location for a possible error
+ *
+ * Serializes the object properties of @config to the file specified
+ * by @file. If a file with that name already exists, it is
+ * overwritten. Basically this function opens @file for you and calls
+ * the serialize function of the @config's #GimpConfigInterface.
+ *
+ * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_config_serialize_to_gfile (GimpConfig *config,
+ GFile *file,
+ const gchar *header,
+ const gchar *footer,
+ gpointer data,
+ GError **error)
+{
+ GimpConfigWriter *writer;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ writer = gimp_config_writer_new_gfile (file, TRUE, header, error);
+ if (!writer)
+ return FALSE;
+
+ GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
+
+ return gimp_config_writer_finish (writer, footer, error);
+}
+
+/**
+ * gimp_config_serialize_to_stream:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @output: the #GOutputStream to write the configuration to.
+ * @header: optional file header (must be ASCII only)
+ * @footer: optional file footer (must be ASCII only)
+ * @data: user data passed to the serialize implementation.
+ * @error: return location for a possible error
+ *
+ * Serializes the object properties of @config to the stream specified
+ * by @output.
+ *
+ * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_config_serialize_to_stream (GimpConfig *config,
+ GOutputStream *output,
+ const gchar *header,
+ const gchar *footer,
+ gpointer data,
+ GError **error)
+{
+ GimpConfigWriter *writer;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ writer = gimp_config_writer_new_stream (output, header, error);
+ if (!writer)
+ return FALSE;
+
+ GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
+
+ return gimp_config_writer_finish (writer, footer, error);
+}
+
+/**
+ * gimp_config_serialize_to_fd:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @fd: a file descriptor, opened for writing
+ * @data: user data passed to the serialize implementation.
+ *
+ * Serializes the object properties of @config to the given file
+ * descriptor.
+ *
+ * Return value: %TRUE if serialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_serialize_to_fd (GimpConfig *config,
+ gint fd,
+ gpointer data)
+{
+ GimpConfigWriter *writer;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (fd > 0, FALSE);
+
+ writer = gimp_config_writer_new_fd (fd);
+ if (!writer)
+ return FALSE;
+
+ GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
+
+ return gimp_config_writer_finish (writer, NULL, NULL);
+}
+
+/**
+ * gimp_config_serialize_to_string:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @data: user data passed to the serialize implementation.
+ *
+ * Serializes the object properties of @config to a string.
+ *
+ * Return value: a newly allocated NUL-terminated string.
+ *
+ * Since: 2.4
+ **/
+gchar *
+gimp_config_serialize_to_string (GimpConfig *config,
+ gpointer data)
+{
+ GimpConfigWriter *writer;
+ GString *str;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
+
+ str = g_string_new (NULL);
+ writer = gimp_config_writer_new_string (str);
+
+ GIMP_CONFIG_GET_INTERFACE (config)->serialize (config, writer, data);
+
+ gimp_config_writer_finish (writer, NULL, NULL);
+
+ return g_string_free (str, FALSE);
+}
+
+/**
+ * gimp_config_deserialize_file:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @filename: the name of the file to read configuration from.
+ * @data: user data passed to the deserialize implementation.
+ * @error: return location for a possible error
+ *
+ * Opens the file specified by @filename, reads configuration data
+ * from it and configures @config accordingly. Basically this function
+ * creates a properly configured #GScanner for you and calls the
+ * deserialize function of the @config's #GimpConfigInterface.
+ *
+ * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_deserialize_file (GimpConfig *config,
+ const gchar *filename,
+ gpointer data,
+ GError **error)
+{
+ GScanner *scanner;
+ gboolean success;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ scanner = gimp_scanner_new_file (filename, error);
+ if (! scanner)
+ return FALSE;
+
+ g_object_freeze_notify (G_OBJECT (config));
+
+ success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
+ scanner, 0, data);
+
+ g_object_thaw_notify (G_OBJECT (config));
+
+ gimp_scanner_destroy (scanner);
+
+ if (! success)
+ g_assert (error == NULL || *error != NULL);
+
+ return success;
+}
+
+/**
+ * gimp_config_deserialize_gfile:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @file: the #GFile to read configuration from.
+ * @data: user data passed to the deserialize implementation.
+ * @error: return location for a possible error
+ *
+ * Opens the file specified by @file, reads configuration data from it
+ * and configures @config accordingly. Basically this function creates
+ * a properly configured #GScanner for you and calls the deserialize
+ * function of the @config's #GimpConfigInterface.
+ *
+ * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_config_deserialize_gfile (GimpConfig *config,
+ GFile *file,
+ gpointer data,
+ GError **error)
+{
+ GScanner *scanner;
+ gboolean success;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ scanner = gimp_scanner_new_gfile (file, error);
+ if (! scanner)
+ return FALSE;
+
+ g_object_freeze_notify (G_OBJECT (config));
+
+ success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
+ scanner, 0, data);
+
+ g_object_thaw_notify (G_OBJECT (config));
+
+ gimp_scanner_destroy (scanner);
+
+ if (! success)
+ g_assert (error == NULL || *error != NULL);
+
+ return success;
+}
+
+/**
+ * gimp_config_deserialize_stream:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @input: the #GInputStream to read configuration from.
+ * @data: user data passed to the deserialize implementation.
+ * @error: return location for a possible error
+ *
+ * Reads configuration data from @input and configures @config
+ * accordingly. Basically this function creates a properly configured
+ * #GScanner for you and calls the deserialize function of the
+ * @config's #GimpConfigInterface.
+ *
+ * Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_config_deserialize_stream (GimpConfig *config,
+ GInputStream *input,
+ gpointer data,
+ GError **error)
+{
+ GScanner *scanner;
+ gboolean success;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ scanner = gimp_scanner_new_stream (input, error);
+ if (! scanner)
+ return FALSE;
+
+ g_object_freeze_notify (G_OBJECT (config));
+
+ success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
+ scanner, 0, data);
+
+ g_object_thaw_notify (G_OBJECT (config));
+
+ gimp_scanner_destroy (scanner);
+
+ if (! success)
+ g_assert (error == NULL || *error != NULL);
+
+ return success;
+}
+
+/**
+ * gimp_config_deserialize_string:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @text: string to deserialize (in UTF-8 encoding)
+ * @text_len: length of @text in bytes or -1
+ * @data: client data
+ * @error: return location for a possible error
+ *
+ * Configures @config from @text. Basically this function creates a
+ * properly configured #GScanner for you and calls the deserialize
+ * function of the @config's #GimpConfigInterface.
+ *
+ * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_deserialize_string (GimpConfig *config,
+ const gchar *text,
+ gint text_len,
+ gpointer data,
+ GError **error)
+{
+ GScanner *scanner;
+ gboolean success;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+ g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ scanner = gimp_scanner_new_string (text, text_len, error);
+
+ g_object_freeze_notify (G_OBJECT (config));
+
+ success = GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
+ scanner, 0, data);
+
+ g_object_thaw_notify (G_OBJECT (config));
+
+ gimp_scanner_destroy (scanner);
+
+ if (! success)
+ g_assert (error == NULL || *error != NULL);
+
+ return success;
+}
+
+/**
+ * gimp_config_deserialize_return:
+ * @scanner: a #GScanner
+ * @expected_token: the expected token
+ * @nest_level: the nest level
+ *
+ * Returns:
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_deserialize_return (GScanner *scanner,
+ GTokenType expected_token,
+ gint nest_level)
+{
+ GTokenType next_token;
+
+ g_return_val_if_fail (scanner != NULL, FALSE);
+
+ next_token = g_scanner_peek_next_token (scanner);
+
+ if (expected_token != G_TOKEN_LEFT_PAREN)
+ {
+ g_scanner_get_next_token (scanner);
+ g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
+ _("fatal parse error"), TRUE);
+ return FALSE;
+ }
+ else
+ {
+ if (nest_level > 0 && next_token == G_TOKEN_RIGHT_PAREN)
+ {
+ return TRUE;
+ }
+ else if (next_token != G_TOKEN_EOF)
+ {
+ g_scanner_get_next_token (scanner);
+ g_scanner_unexp_token (scanner, expected_token, NULL, NULL, NULL,
+ _("fatal parse error"), TRUE);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * gimp_config_serialize:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @writer: the #GimpConfigWriter to use.
+ * @data: client data
+ *
+ * Serialize the #GimpConfig object.
+ *
+ * Returns: %TRUE if serialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.8
+ **/
+gboolean
+gimp_config_serialize (GimpConfig *config,
+ GimpConfigWriter *writer,
+ gpointer data)
+{
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+
+ return GIMP_CONFIG_GET_INTERFACE (config)->serialize (config,
+ writer,
+ data);
+}
+
+/**
+ * gimp_config_deserialize:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ * @scanner: the #GScanner to use.
+ * @nest_level: the nest level.
+ * @data: client data.
+ *
+ * Deserialize the #GimpConfig object.
+ *
+ * Returns: %TRUE if deserialization succeeded, %FALSE otherwise.
+ *
+ * Since: 2.8
+ **/
+gboolean
+gimp_config_deserialize (GimpConfig *config,
+ GScanner *scanner,
+ gint nest_level,
+ gpointer data)
+{
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
+
+ return GIMP_CONFIG_GET_INTERFACE (config)->deserialize (config,
+ scanner,
+ nest_level,
+ data);
+}
+
+/**
+ * gimp_config_duplicate:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ *
+ * Creates a copy of the passed object by copying all object
+ * properties. The default implementation of the #GimpConfigInterface
+ * only works for objects that are completely defined by their
+ * properties.
+ *
+ * Return value: the duplicated #GimpConfig object
+ *
+ * Since: 2.4
+ **/
+gpointer
+gimp_config_duplicate (GimpConfig *config)
+{
+ g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
+
+ return GIMP_CONFIG_GET_INTERFACE (config)->duplicate (config);
+}
+
+/**
+ * gimp_config_is_equal_to:
+ * @a: a #GObject that implements the #GimpConfigInterface.
+ * @b: another #GObject of the same type as @a.
+ *
+ * Compares the two objects. The default implementation of the
+ * #GimpConfigInterface compares the object properties and thus only
+ * works for objects that are completely defined by their
+ * properties.
+ *
+ * Return value: %TRUE if the two objects are equal.
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_config_is_equal_to (GimpConfig *a,
+ GimpConfig *b)
+{
+ g_return_val_if_fail (GIMP_IS_CONFIG (a), FALSE);
+ g_return_val_if_fail (GIMP_IS_CONFIG (b), FALSE);
+ g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b),
+ FALSE);
+
+ return GIMP_CONFIG_GET_INTERFACE (a)->equal (a, b);
+}
+
+/**
+ * gimp_config_reset:
+ * @config: a #GObject that implements the #GimpConfigInterface.
+ *
+ * Resets the object to its default state. The default implementation of the
+ * #GimpConfigInterface only works for objects that are completely defined by
+ * their properties.
+ *
+ * Since: 2.4
+ **/
+void
+gimp_config_reset (GimpConfig *config)
+{
+ g_return_if_fail (GIMP_IS_CONFIG (config));
+
+ g_object_freeze_notify (G_OBJECT (config));
+
+ GIMP_CONFIG_GET_INTERFACE (config)->reset (config);
+
+ g_object_thaw_notify (G_OBJECT (config));
+}
+
+/**
+ * gimp_config_copy:
+ * @src: a #GObject that implements the #GimpConfigInterface.
+ * @dest: another #GObject of the same type as @a.
+ * @flags: a mask of GParamFlags
+ *
+ * Compares all read- and write-able properties from @src and @dest
+ * that have all @flags set. Differing values are then copied from
+ * @src to @dest. If @flags is 0, all differing read/write properties.
+ *
+ * Properties marked as "construct-only" are not touched.
+ *
+ * Return value: %TRUE if @dest was modified, %FALSE otherwise
+ *
+ * Since: 2.6
+ **/
+gboolean
+gimp_config_copy (GimpConfig *src,
+ GimpConfig *dest,
+ GParamFlags flags)
+{
+ gboolean changed;
+
+ g_return_val_if_fail (GIMP_IS_CONFIG (src), FALSE);
+ g_return_val_if_fail (GIMP_IS_CONFIG (dest), FALSE);
+ g_return_val_if_fail (G_TYPE_FROM_INSTANCE (src) == G_TYPE_FROM_INSTANCE (dest),
+ FALSE);
+
+ g_object_freeze_notify (G_OBJECT (dest));
+
+ changed = GIMP_CONFIG_GET_INTERFACE (src)->copy (src, dest, flags);
+
+ g_object_thaw_notify (G_OBJECT (dest));
+
+ return changed;
+}