405 lines
11 KiB
C
405 lines
11 KiB
C
![]() |
/*
|
||
|
* This file is part of The Croco Library
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation.
|
||
|
*
|
||
|
* 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 Lesser General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||
|
* USA
|
||
|
*
|
||
|
* Author: Dodji Seketeli
|
||
|
* See COPYRIGHTS file for copyrights information.
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include "cr-prop-list.h"
|
||
|
|
||
|
#define PRIVATE(a_obj) (a_obj)->priv
|
||
|
|
||
|
struct _CRPropListPriv {
|
||
|
CRString *prop;
|
||
|
CRDeclaration *decl;
|
||
|
CRPropList *next;
|
||
|
CRPropList *prev;
|
||
|
};
|
||
|
|
||
|
static CRPropList *cr_prop_list_allocate (void);
|
||
|
|
||
|
/**
|
||
|
*Default allocator of CRPropList
|
||
|
*@return the newly allocated CRPropList or NULL
|
||
|
*if an error arises.
|
||
|
*/
|
||
|
static CRPropList *
|
||
|
cr_prop_list_allocate (void)
|
||
|
{
|
||
|
CRPropList *result = NULL;
|
||
|
|
||
|
result = g_try_malloc (sizeof (CRPropList));
|
||
|
if (!result) {
|
||
|
cr_utils_trace_info ("could not allocate CRPropList");
|
||
|
return NULL;
|
||
|
}
|
||
|
memset (result, 0, sizeof (CRPropList));
|
||
|
PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
|
||
|
if (!result) {
|
||
|
cr_utils_trace_info ("could not allocate CRPropListPriv");
|
||
|
g_free (result);
|
||
|
return NULL;
|
||
|
}
|
||
|
memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/****************
|
||
|
*public methods
|
||
|
***************/
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_append:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_to_append: the property list to append
|
||
|
*
|
||
|
*Appends a property list to the current one.
|
||
|
*
|
||
|
*Returns the resulting prop list, or NULL if an error
|
||
|
*occurred
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
|
||
|
{
|
||
|
CRPropList *cur = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_to_append, NULL);
|
||
|
|
||
|
if (!a_this)
|
||
|
return a_to_append;
|
||
|
|
||
|
/*go fetch the last element of the list */
|
||
|
for (cur = a_this;
|
||
|
cur && PRIVATE (cur) && PRIVATE (cur)->next;
|
||
|
cur = PRIVATE (cur)->next) ;
|
||
|
g_return_val_if_fail (cur, NULL);
|
||
|
PRIVATE (cur)->next = a_to_append;
|
||
|
PRIVATE (a_to_append)->prev = cur;
|
||
|
return a_this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_append2:
|
||
|
*Appends a pair of prop/declaration to
|
||
|
*the current prop list.
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_prop: the property to consider
|
||
|
*@a_decl: the declaration to consider
|
||
|
*
|
||
|
*Returns the resulting property list, or NULL in case
|
||
|
*of an error.
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_append2 (CRPropList * a_this,
|
||
|
CRString * a_prop,
|
||
|
CRDeclaration * a_decl)
|
||
|
{
|
||
|
CRPropList *list = NULL,
|
||
|
*result = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_prop && a_decl, NULL);
|
||
|
|
||
|
list = cr_prop_list_allocate ();
|
||
|
g_return_val_if_fail (list && PRIVATE (list), NULL);
|
||
|
|
||
|
PRIVATE (list)->prop = a_prop;
|
||
|
PRIVATE (list)->decl = a_decl;
|
||
|
|
||
|
result = cr_prop_list_append (a_this, list);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_prepend:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_to_prepend: the new list to prepend.
|
||
|
*
|
||
|
*Prepends a list to the current list
|
||
|
*Returns the new properties list.
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
|
||
|
{
|
||
|
CRPropList *cur = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_to_prepend, NULL);
|
||
|
|
||
|
if (!a_this)
|
||
|
return a_to_prepend;
|
||
|
|
||
|
for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
|
||
|
cur = PRIVATE (cur)->next) ;
|
||
|
g_return_val_if_fail (cur, NULL);
|
||
|
PRIVATE (cur)->next = a_this;
|
||
|
PRIVATE (a_this)->prev = cur;
|
||
|
return a_to_prepend;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_prepend2:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_prop_name: property name to append
|
||
|
*@a_decl: the property value to append.
|
||
|
*
|
||
|
*Prepends a propertie to a list of properties
|
||
|
*
|
||
|
*Returns the new property list.
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_prepend2 (CRPropList * a_this,
|
||
|
CRString * a_prop_name, CRDeclaration * a_decl)
|
||
|
{
|
||
|
CRPropList *list = NULL,
|
||
|
*result = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
||
|
&& a_prop_name && a_decl, NULL);
|
||
|
|
||
|
list = cr_prop_list_allocate ();
|
||
|
g_return_val_if_fail (list, NULL);
|
||
|
PRIVATE (list)->prop = a_prop_name;
|
||
|
PRIVATE (list)->decl = a_decl;
|
||
|
result = cr_prop_list_prepend (a_this, list);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_set_prop:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_prop: the property to set
|
||
|
*
|
||
|
*Sets the property of a CRPropList
|
||
|
*/
|
||
|
enum CRStatus
|
||
|
cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
||
|
&& a_prop, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
PRIVATE (a_this)->prop = a_prop;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_get_prop:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_prop: out parameter. The returned property
|
||
|
*
|
||
|
*Getter of the property associated to the current instance
|
||
|
*of #CRPropList
|
||
|
*
|
||
|
*Returns CR_OK upon successful completion, an error code
|
||
|
*otherwise.
|
||
|
*/
|
||
|
enum CRStatus
|
||
|
cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
||
|
&& a_prop, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
*a_prop = PRIVATE (a_this)->prop;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_set_decl:
|
||
|
* @a_this: the current instance of #CRPropList
|
||
|
* @a_decl: the new property value.
|
||
|
*
|
||
|
* Returns CR_OK upon successful completion, an error code otherwise.
|
||
|
*/
|
||
|
enum CRStatus
|
||
|
cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
||
|
&& a_decl, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
PRIVATE (a_this)->decl = a_decl;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_get_decl:
|
||
|
* @a_this: the current instance of #CRPropList
|
||
|
* @a_decl: out parameter. The property value
|
||
|
*
|
||
|
* Returns CR_OK upon successful completion.
|
||
|
*/
|
||
|
enum CRStatus
|
||
|
cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
||
|
&& a_decl, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
*a_decl = PRIVATE (a_this)->decl;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_lookup_prop:
|
||
|
*@a_this: the current instance of #CRPropList
|
||
|
*@a_prop: the property to lookup
|
||
|
*@a_prop_list: out parameter. The property/declaration
|
||
|
*pair found (if and only if the function returned code if CR_OK)
|
||
|
*
|
||
|
*Lookup a given property/declaration pair
|
||
|
*
|
||
|
*Returns CR_OK if a prop/decl pair has been found,
|
||
|
*CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
|
||
|
*bad happens.
|
||
|
*/
|
||
|
enum CRStatus
|
||
|
cr_prop_list_lookup_prop (CRPropList * a_this,
|
||
|
CRString * a_prop, CRPropList ** a_pair)
|
||
|
{
|
||
|
CRPropList *cur = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
if (!a_this)
|
||
|
return CR_VALUE_NOT_FOUND_ERROR;
|
||
|
|
||
|
g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
|
||
|
if (PRIVATE (cur)->prop
|
||
|
&& PRIVATE (cur)->prop->stryng
|
||
|
&& PRIVATE (cur)->prop->stryng->str
|
||
|
&& a_prop->stryng
|
||
|
&& a_prop->stryng->str
|
||
|
&& !strcmp (PRIVATE (cur)->prop->stryng->str,
|
||
|
a_prop->stryng->str))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (cur) {
|
||
|
*a_pair = cur;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
return CR_VALUE_NOT_FOUND_ERROR;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_get_next:
|
||
|
*@a_this: the current instance of CRPropList
|
||
|
*
|
||
|
*Gets the next prop/decl pair in the list
|
||
|
*
|
||
|
*Returns the next prop/declaration pair of the list,
|
||
|
*or NULL if we reached end of list (or if an error occurs)
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_get_next (CRPropList * a_this)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
|
||
|
|
||
|
return PRIVATE (a_this)->next;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_get_prev:
|
||
|
*@a_this: the current instance of CRPropList
|
||
|
*
|
||
|
*Gets the previous prop/decl pair in the list
|
||
|
*
|
||
|
*Returns the previous prop/declaration pair of the list,
|
||
|
*or NULL if we reached end of list (or if an error occurs)
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_get_prev (CRPropList * a_this)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
|
||
|
|
||
|
return PRIVATE (a_this)->prev;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_unlink:
|
||
|
*@a_this: the current list of prop/decl pairs
|
||
|
*@a_pair: the prop/decl pair to unlink.
|
||
|
*
|
||
|
*Unlinks a prop/decl pair from the list
|
||
|
*
|
||
|
*Returns the new list or NULL in case of an error.
|
||
|
*/
|
||
|
CRPropList *
|
||
|
cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
|
||
|
{
|
||
|
CRPropList *prev = NULL,
|
||
|
*next = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
|
||
|
|
||
|
/*some sanity checks */
|
||
|
if (PRIVATE (a_pair)->next) {
|
||
|
next = PRIVATE (a_pair)->next;
|
||
|
g_return_val_if_fail (PRIVATE (next), NULL);
|
||
|
g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
|
||
|
}
|
||
|
if (PRIVATE (a_pair)->prev) {
|
||
|
prev = PRIVATE (a_pair)->prev;
|
||
|
g_return_val_if_fail (PRIVATE (prev), NULL);
|
||
|
g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
|
||
|
}
|
||
|
if (prev) {
|
||
|
PRIVATE (prev)->next = next;
|
||
|
}
|
||
|
if (next) {
|
||
|
PRIVATE (next)->prev = prev;
|
||
|
}
|
||
|
PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
|
||
|
if (a_this == a_pair) {
|
||
|
if (next)
|
||
|
return next;
|
||
|
return NULL;
|
||
|
}
|
||
|
return a_this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cr_prop_list_destroy:
|
||
|
* @a_this: the current instance of #CRPropList
|
||
|
*/
|
||
|
void
|
||
|
cr_prop_list_destroy (CRPropList * a_this)
|
||
|
{
|
||
|
CRPropList *tail = NULL,
|
||
|
*cur = NULL;
|
||
|
|
||
|
g_return_if_fail (a_this && PRIVATE (a_this));
|
||
|
|
||
|
for (tail = a_this;
|
||
|
tail && PRIVATE (tail) && PRIVATE (tail)->next;
|
||
|
tail = cr_prop_list_get_next (tail)) ;
|
||
|
g_return_if_fail (tail);
|
||
|
|
||
|
cur = tail;
|
||
|
|
||
|
while (cur) {
|
||
|
tail = PRIVATE (cur)->prev;
|
||
|
if (tail && PRIVATE (tail))
|
||
|
PRIVATE (tail)->next = NULL;
|
||
|
PRIVATE (cur)->prev = NULL;
|
||
|
g_free (PRIVATE (cur));
|
||
|
PRIVATE (cur) = NULL;
|
||
|
g_free (cur);
|
||
|
cur = tail;
|
||
|
}
|
||
|
}
|