/* * 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 #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 property 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; } }