Skip to content
Snippets Groups Projects
configuration.c 5.77 KiB
Newer Older
/* 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);

        g_debug ("loading config file: %s", location);

        if (!wp_config_parser_add_file (parser, location))
          g_warning ("Failed to parse file '%s'", location);
      }
    }

    /* Close the directory */
    g_dir_close (conf_dir);
  }
}