Commit 77ec4c54 authored by Julian Bouzas's avatar Julian Bouzas
Browse files

lib: introduce WpConfiguration

The purpose of this change is to have a generic API that allows modules to read
configuration data from files under a specific directory. Since we can have many
types of configuration files, this new class maps file extensions with generic
parsers defined in the modules, giving modules full freedom to parse any kind of
data.
parent 9a9d773b
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include "configuration.h"
#include "private.h"
struct _WpConfiguration
{
GObject parent;
GPtrArray *paths;
GHashTable *parsers;
};
G_DEFINE_INTERFACE (WpConfigParser, wp_config_parser, G_TYPE_OBJECT)
static void
wp_config_parser_default_init (WpConfigParserInterface *klass)
{
}
gboolean
wp_config_parser_add_file (WpConfigParser *self, const char *location)
{
g_return_val_if_fail (WP_IS_CONFIG_PARSER (self), FALSE);
g_return_val_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->add_file, FALSE);
return WP_CONFIG_PARSER_GET_IFACE (self)->add_file (self, location);
}
gconstpointer
wp_config_parser_get_matched_data (WpConfigParser *self, gpointer data)
{
g_return_val_if_fail (WP_IS_CONFIG_PARSER (self), NULL);
g_return_val_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->get_matched_data, NULL);
return WP_CONFIG_PARSER_GET_IFACE (self)->get_matched_data (self, data);
}
void
wp_config_parser_reset (WpConfigParser *self)
{
g_return_if_fail (WP_IS_CONFIG_PARSER (self));
g_return_if_fail (WP_CONFIG_PARSER_GET_IFACE (self)->reset);
WP_CONFIG_PARSER_GET_IFACE (self)->reset (self);
}
G_DEFINE_TYPE (WpConfiguration, wp_configuration, G_TYPE_OBJECT)
static void
wp_configuration_finalize (GObject * obj)
{
WpConfiguration * self = WP_CONFIGURATION (obj);
g_clear_pointer (&self->paths, g_ptr_array_unref);
g_clear_pointer (&self->parsers, g_hash_table_unref);
G_OBJECT_CLASS (wp_configuration_parent_class)->finalize (obj);
}
static void
wp_configuration_init (WpConfiguration * self)
{
self->paths = g_ptr_array_new_with_free_func (g_free);
self->parsers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
g_object_unref);
}
static void
wp_configuration_class_init (WpConfigurationClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = wp_configuration_finalize;
}
WpConfiguration *
wp_configuration_get_instance (WpCore *core)
{
WpConfiguration *self;
g_return_val_if_fail (WP_IS_CORE (core), NULL);
self = wp_core_find_object (core, (GEqualFunc) WP_IS_CONFIGURATION, NULL);
if (!self) {
self = g_object_new (WP_TYPE_CONFIGURATION, NULL);
wp_core_register_object (core, g_object_ref (self));
}
return self;
}
void
wp_configuration_add_path (WpConfiguration *self, const char *path)
{
guint i;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Make sure the path is not already added */
for (i = 0; i < self->paths->len; i++) {
const char *p = g_ptr_array_index(self->paths, i);
if (g_strcmp0(p, path) == 0)
return;
}
g_ptr_array_add (self->paths, g_strdup (path));
}
void
wp_configuration_remove_path (WpConfiguration *self, const char *path)
{
guint i;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Find the path index */
for (i = 0; i < self->paths->len; i++) {
const char *p = g_ptr_array_index(self->paths, i);
if (g_strcmp0(p, path) == 0)
break;
}
/* Only remove the path if the index is valid */
if (i < self->paths->len)
g_ptr_array_remove_index (self->paths, i);
}
gboolean
wp_configuration_add_extension (WpConfiguration *self, const gchar * extension,
GType parser_type)
{
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
/* create the parser */
g_autoptr (WpConfigParser) parser = g_object_new (parser_type, FALSE);
g_return_val_if_fail (WP_IS_CONFIG_PARSER (parser), FALSE);
return g_hash_table_insert (self->parsers, g_strdup (extension),
g_steal_pointer (&parser));
}
gboolean
wp_configuration_remove_extension (WpConfiguration *self,
const gchar * extension)
{
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), FALSE);
return g_hash_table_remove (self->parsers, extension);
}
WpConfigParser *
wp_configuration_get_parser (WpConfiguration *self, const char *extension)
{
WpConfigParser *parser = NULL;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (WP_IS_CONFIGURATION (self), NULL);
parser = g_hash_table_lookup (self->parsers, extension);
return parser ? g_object_ref (parser) : NULL;
}
void
wp_configuration_reload (WpConfiguration *self, const char *extension)
{
guint i;
const char *path = NULL;
GDir* conf_dir = NULL;
GError* error = NULL;
const gchar *file_name = NULL;
g_autofree gchar *ext = NULL;
g_autofree gchar *location = NULL;
g_return_if_fail (self);
g_return_if_fail (WP_IS_CONFIGURATION (self));
/* Get the parser for the extension */
WpConfigParser *parser = g_hash_table_lookup (self->parsers, extension);
if (!parser) {
g_warning ("Could not find parser for extension '%s'", extension);
return;
}
/* Reset the parser */
wp_config_parser_reset (parser);
/* Load extension files in all paths */
for (i = 0; i < self->paths->len; i++) {
/* Get the path */
path = g_ptr_array_index(self->paths, i);
/* Open the directory */
conf_dir = g_dir_open (path, 0, &error);
if (!conf_dir) {
g_warning ("Could not open configuration path '%s'", path);
continue;
}
/* Parse each configuration file matching the extension */
ext = g_strdup_printf (".%s", extension);
while ((file_name = g_dir_read_name (conf_dir))) {
/* Only parse files that have the proper extension */
if (g_str_has_suffix (file_name, ext)) {
location = g_build_filename (path, file_name, NULL);
if (!wp_config_parser_add_file (parser, location))
g_warning ("Failed to parse file '%s'", location);
}
}
/* Close the directory */
g_dir_close (conf_dir);
}
}
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_CONFIGURATION_H__
#define __WIREPLUMBER_CONFIGURATION_H__
#include "core.h"
G_BEGIN_DECLS
#define WP_TYPE_CONFIG_PARSER (wp_config_parser_get_type ())
G_DECLARE_INTERFACE (WpConfigParser, wp_config_parser, WP,
CONFIG_PARSER, GObject)
struct _WpConfigParserInterface
{
GTypeInterface parent;
gboolean (*add_file) (WpConfigParser *parser, const gchar *name);
gconstpointer (*get_matched_data) (WpConfigParser *parser, gpointer data);
void (*reset) (WpConfigParser *parser);
};
gboolean wp_config_parser_add_file (WpConfigParser *self, const char *location);
gconstpointer wp_config_parser_get_matched_data (WpConfigParser *self,
gpointer data);
void wp_config_parser_reset (WpConfigParser *self);
#define WP_TYPE_CONFIGURATION (wp_configuration_get_type ())
G_DECLARE_FINAL_TYPE (WpConfiguration, wp_configuration, WP, CONFIGURATION,
GObject)
WpConfiguration * wp_configuration_get_instance (WpCore *core);
void wp_configuration_add_path (WpConfiguration *self, const char *path);
void wp_configuration_remove_path (WpConfiguration *self, const char *path);
gboolean wp_configuration_add_extension (WpConfiguration *self,
const gchar * extension, GType parser_type);
gboolean wp_configuration_remove_extension (WpConfiguration *self,
const gchar * extension);
WpConfigParser *wp_configuration_get_parser (WpConfiguration *self,
const char *extension);
void wp_configuration_reload (WpConfiguration *self, const char *extension);
G_END_DECLS
#endif
wp_lib_sources = [
'configuration.c',
'core.c',
'endpoint.c',
'error.c',
......@@ -19,6 +20,7 @@ wp_lib_sources = [
]
wp_lib_headers = [
'configuration.h',
'core.h',
'endpoint.h',
'error.h',
......
......@@ -6,6 +6,7 @@
* SPDX-License-Identifier: MIT
*/
#include "configuration.h"
#include "core.h"
#include "endpoint.h"
#include "error.h"
......
Supports Markdown
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