/* * 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 ***************/ /** *Appends a property list to the current one. *@param a_this the current instance of #CRPropList *@param a_to_append the property list to append *@return the resulting prop list, or NULL if an error *occured */ 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; } /** *Appends a pair of prop/declaration to *the current prop list. *@param a_this the current instance of #CRPropList *@param a_prop the property to consider *@param a_decl the declaration to consider *@return 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; } /** *Prepends a list to the current list *@param a_this the current instance of #CRPropList *@param the new list to prepend. */ 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; } /** *Prepends a list to the current list *@param a_this the current instance of #CRPropList *@param the new list to prepend. */ CRPropList * cr_prop_list_prepend2 (CRPropList * a_this, CRString * a_prop, CRDeclaration * a_decl) { CRPropList *list = NULL, *result = NULL; g_return_val_if_fail (a_this && PRIVATE (a_this) && a_prop && a_decl, NULL); list = cr_prop_list_allocate (); g_return_val_if_fail (list, NULL); PRIVATE (list)->prop = a_prop; PRIVATE (list)->decl = a_decl; result = cr_prop_list_prepend (a_this, list); return result; } /** *Sets the property of a CRPropList *@param a_this the current instance of #CRPropList *@param a_prop the property to set */ 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; } /** *Getter of the property associated to the current instance *of #CRPropList *@param a_this the current instance of #CRPropList *@param a_prop out parameter. The returned property *@return CR_OK upon successful completion, an error code *otherwise. */ enum CRStatus cr_prop_list_get_prop (CRPropList * 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; } 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; } enum CRStatus cr_prop_list_get_decl (CRPropList * 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; } /** *Lookup a given property/declaration pair *@param a_this the current instance of #CRPropList *@param a_prop the property to lookup *@param a_prop_list out parameter. The property/declaration *pair found (if and only if the function returned code if CR_OK) *@return 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; } /** *Gets the next prop/decl pair in the list *@param a_this the current instance of CRPropList *@param the next prop/decl pair, or NULL if we *reached the end of the list. *@return 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; } /** *Gets the previous prop/decl pair in the list *@param a_this the current instance of CRPropList *@param the previous prop/decl pair, or NULL if we *reached the end of the list. *@return 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; } /** *Unlinks a prop/decl pair from the list *@param a_this the current list of prop/decl pairs *@param a_pair the prop/decl pair to unlink. *@return 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; } 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; } }