239 lines
6 KiB
C
239 lines
6 KiB
C
/*
|
|
config_lookup.c - Lookup functions for the config subsystem
|
|
|
|
Copyright (C) Lumiera.org
|
|
2008, Christian Thaeter <ct@pipapo.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
#include "lib/safeclib.h"
|
|
|
|
#include "backend/config_lookup.h"
|
|
#include "backend/config.h"
|
|
|
|
/* we only use one fatal error for now, when allocation in the config system fail, something else is pretty wrong */
|
|
LUMIERA_ERROR_DEFINE (CONFIG_LOOKUP, "config lookup failure");
|
|
|
|
/*
|
|
support functions for the splay tree
|
|
*/
|
|
static int
|
|
cmp_fn (const void* a, const void* b);
|
|
|
|
static void
|
|
delete_fn (PSplaynode node);
|
|
|
|
static const void*
|
|
key_fn (const PSplaynode node);
|
|
|
|
|
|
/**
|
|
* @file
|
|
* Implementation of the lookup of configuration keys
|
|
*/
|
|
|
|
|
|
LumieraConfigLookup
|
|
lumiera_config_lookup_init (LumieraConfigLookup self)
|
|
{
|
|
TRACE (config_lookup);
|
|
psplay_init (&self->tree, cmp_fn, key_fn, delete_fn);
|
|
return self;
|
|
}
|
|
|
|
|
|
LumieraConfigLookup
|
|
lumiera_config_lookup_destroy (LumieraConfigLookup self)
|
|
{
|
|
TRACE (config_lookup);
|
|
if (self)
|
|
psplay_destroy (&self->tree);
|
|
return self;
|
|
}
|
|
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookup_insert (LumieraConfigLookup self, LumieraConfigitem item)
|
|
{
|
|
TRACE (config_lookup);
|
|
REQUIRE (self);
|
|
REQUIRE (item);
|
|
REQUIRE (item->key);
|
|
REQUIRE (item->key_size);
|
|
|
|
FIXME ("implement section prefix/suffix for the key");
|
|
const char* key = lumiera_tmpbuf_strcat3 (NULL, 0, item->key, item->key_size, NULL, 0);
|
|
|
|
LumieraConfigLookupentry entry = (LumieraConfigLookupentry)psplay_find (&self->tree, key, 100);
|
|
if (!entry)
|
|
entry = (LumieraConfigLookupentry)psplay_insert (&self->tree, &lumiera_config_lookupentry_new (key)->node, 100);
|
|
|
|
llist_insert_head (&entry->configitems, &item->lookup);
|
|
return entry;
|
|
}
|
|
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookup_insert_default (LumieraConfigLookup self, LumieraConfigitem item)
|
|
{
|
|
TRACE (config_lookup);
|
|
REQUIRE (self);
|
|
REQUIRE (item);
|
|
REQUIRE (item->key);
|
|
REQUIRE (item->key_size);
|
|
|
|
const char* key = lumiera_tmpbuf_snprintf (SIZE_MAX, "%.*s", item->key_size, item->key);
|
|
LumieraConfigLookupentry entry = (LumieraConfigLookupentry)psplay_find (&self->tree, key, 100);
|
|
if (!entry)
|
|
entry = (LumieraConfigLookupentry)psplay_insert (&self->tree, &lumiera_config_lookupentry_new (key)->node, 100);
|
|
TODO ("else check that no 'default' item already exists, that is, the tail element's parent points to the 'defaults' in config");
|
|
|
|
llist_insert_tail (&entry->configitems, &item->lookup);
|
|
return entry;
|
|
}
|
|
|
|
|
|
LumieraConfigitem
|
|
lumiera_config_lookup_remove (LumieraConfigLookup self, LumieraConfigitem item)
|
|
{
|
|
TRACE (config_lookup);
|
|
REQUIRE (!llist_is_empty (&item->lookup), "item is not in a lookup");
|
|
|
|
if (llist_is_single (&item->lookup))
|
|
{
|
|
/* last item in lookup, remove it from the splay tree */
|
|
LumieraConfigLookupentry entry = LLIST_TO_STRUCTP (llist_next (&item->lookup), lumiera_config_lookupentry, configitems);
|
|
llist_unlink (&item->lookup);
|
|
psplay_delete_node (&self->tree, (PSplaynode)entry);
|
|
}
|
|
else
|
|
{
|
|
/* more than this item present in hash, just unlink this item */
|
|
llist_unlink (&item->lookup);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookup_find (LumieraConfigLookup self, const char* key)
|
|
{
|
|
TRACE (config_lookup);
|
|
return (LumieraConfigLookupentry)psplay_find (&self->tree, key, 100);
|
|
}
|
|
|
|
|
|
LumieraConfigitem
|
|
lumiera_config_lookup_item_find (LumieraConfigLookup self, const char* key)
|
|
{
|
|
TRACE (config_lookup);
|
|
|
|
LumieraConfigLookupentry entry =
|
|
lumiera_config_lookup_find (self, key);
|
|
|
|
if (entry && !llist_is_empty (&entry->configitems))
|
|
return LLIST_TO_STRUCTP (llist_head (&entry->configitems), lumiera_configitem, lookup);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
LumieraConfigitem
|
|
lumiera_config_lookup_item_tail_find (LumieraConfigLookup self, const char* key)
|
|
{
|
|
TRACE (config_lookup);
|
|
|
|
LumieraConfigLookupentry entry =
|
|
lumiera_config_lookup_find (self, key);
|
|
|
|
if (entry && !llist_is_empty (&entry->configitems))
|
|
return LLIST_TO_STRUCTP (llist_tail (&entry->configitems), lumiera_configitem, lookup);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Lookup entries
|
|
*/
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookupentry_init (LumieraConfigLookupentry self, const char* key)
|
|
{
|
|
TRACE (config_lookup, "key = %s", key);
|
|
if (self)
|
|
{
|
|
psplaynode_init (&self->node);
|
|
llist_init (&self->configitems);
|
|
self->full_key = lumiera_strndup (key, SIZE_MAX);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookupentry_new (const char* key)
|
|
{
|
|
return lumiera_config_lookupentry_init (lumiera_malloc (sizeof (lumiera_config_lookupentry)), key);
|
|
}
|
|
|
|
|
|
LumieraConfigLookupentry
|
|
lumiera_config_lookupentry_destroy (LumieraConfigLookupentry self)
|
|
{
|
|
TRACE (config_lookup);
|
|
if (self)
|
|
{
|
|
REQUIRE (llist_is_empty (&self->configitems), "lookup node still in use");
|
|
lumiera_free (self->full_key);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
void
|
|
lumiera_config_lookupentry_delete (LumieraConfigLookupentry self)
|
|
{
|
|
lumiera_free (lumiera_config_lookupentry_destroy (self));
|
|
}
|
|
|
|
static int
|
|
cmp_fn (const void* a, const void* b)
|
|
{
|
|
return strcmp ((const char*)a, (const char*)b);
|
|
}
|
|
|
|
static void
|
|
delete_fn (PSplaynode node)
|
|
{
|
|
lumiera_config_lookupentry_delete ((LumieraConfigLookupentry) node);
|
|
}
|
|
|
|
|
|
static const void*
|
|
key_fn (const PSplaynode node)
|
|
{
|
|
return ((LumieraConfigLookupentry) node)->full_key;
|
|
}
|
|
|
|
/*
|
|
// Local Variables:
|
|
// mode: C
|
|
// c-file-style: "gnu"
|
|
// indent-tabs-mode: nil
|
|
// End:
|
|
*/
|