Libcroco
cr-prop-list.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of The Croco Library
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of version 2.1 of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this program; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00016  * USA
00017  *
00018  * Author: Dodji Seketeli
00019  * See COPYRIGHTS file for copyrights information.
00020  */
00021 
00022 #include <string.h>
00023 #include "cr-prop-list.h"
00024 
00025 #define PRIVATE(a_obj) (a_obj)->priv
00026 
00027 struct _CRPropListPriv {
00028         CRString *prop;
00029         CRDeclaration *decl;
00030         CRPropList *next;
00031         CRPropList *prev;
00032 };
00033 
00034 static CRPropList *cr_prop_list_allocate (void);
00035 
00036 /**
00037  *Default allocator of CRPropList
00038  *@return the newly allocated CRPropList or NULL
00039  *if an error arises.
00040  */
00041 static CRPropList *
00042 cr_prop_list_allocate (void)
00043 {
00044         CRPropList *result = NULL;
00045 
00046         result = g_try_malloc (sizeof (CRPropList));
00047         if (!result) {
00048                 cr_utils_trace_info ("could not allocate CRPropList");
00049                 return NULL;
00050         }
00051         memset (result, 0, sizeof (CRPropList));
00052         PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
00053         if (!result) {
00054                 cr_utils_trace_info ("could not allocate CRPropListPriv");
00055                 g_free (result);
00056                 return NULL;
00057         }
00058         memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
00059         return result;
00060 }
00061 
00062 /****************
00063  *public methods
00064  ***************/
00065 
00066 /**
00067  * cr_prop_list_append:
00068  *@a_this: the current instance of #CRPropList
00069  *@a_to_append: the property list to append
00070  *
00071  *Appends a property list to the current one.
00072  *
00073  *Returns the resulting prop list, or NULL if an error
00074  *occurred
00075  */
00076 CRPropList *
00077 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
00078 {
00079         CRPropList *cur = NULL;
00080 
00081         g_return_val_if_fail (a_to_append, NULL);
00082 
00083         if (!a_this)
00084                 return a_to_append;
00085 
00086         /*go fetch the last element of the list */
00087         for (cur = a_this;
00088              cur && PRIVATE (cur) && PRIVATE (cur)->next;
00089              cur = PRIVATE (cur)->next) ;
00090         g_return_val_if_fail (cur, NULL);
00091         PRIVATE (cur)->next = a_to_append;
00092         PRIVATE (a_to_append)->prev = cur;
00093         return a_this;
00094 }
00095 
00096 /**
00097  * cr_prop_list_append2:
00098  *Appends a pair of prop/declaration to
00099  *the current prop list.
00100  *@a_this: the current instance of #CRPropList
00101  *@a_prop: the property to consider
00102  *@a_decl: the declaration to consider
00103  *
00104  *Returns the resulting property list, or NULL in case
00105  *of an error.
00106  */
00107 CRPropList *
00108 cr_prop_list_append2 (CRPropList * a_this,
00109                       CRString * a_prop, 
00110                       CRDeclaration * a_decl)
00111 {
00112         CRPropList *list = NULL,
00113                 *result = NULL;
00114 
00115         g_return_val_if_fail (a_prop && a_decl, NULL);
00116 
00117         list = cr_prop_list_allocate ();
00118         g_return_val_if_fail (list && PRIVATE (list), NULL);
00119 
00120         PRIVATE (list)->prop = a_prop;
00121         PRIVATE (list)->decl = a_decl;
00122 
00123         result = cr_prop_list_append (a_this, list);
00124         return result;
00125 }
00126 
00127 /**
00128  * cr_prop_list_prepend:
00129  *@a_this: the current instance of #CRPropList
00130  *@a_to_prepend: the new list to prepend.
00131  *
00132  *Prepends a list to the current list
00133  *Returns the new properties list.
00134  */
00135 CRPropList *
00136 cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
00137 {
00138         CRPropList *cur = NULL;
00139 
00140         g_return_val_if_fail (a_to_prepend, NULL);
00141 
00142         if (!a_this)
00143                 return a_to_prepend;
00144 
00145         for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
00146              cur = PRIVATE (cur)->next) ;
00147         g_return_val_if_fail (cur, NULL);
00148         PRIVATE (cur)->next = a_this;
00149         PRIVATE (a_this)->prev = cur;
00150         return a_to_prepend;
00151 }
00152 
00153 /**
00154  * cr_prop_list_prepend2:
00155  *@a_this: the current instance of #CRPropList
00156  *@a_prop_name: property name to append
00157  *@a_decl: the property value to append.
00158  *
00159  *Prepends a propertie to a list of properties 
00160  *
00161  *Returns the new property list.
00162  */
00163 CRPropList *
00164 cr_prop_list_prepend2 (CRPropList * a_this,
00165                        CRString * a_prop_name, CRDeclaration * a_decl)
00166 {
00167         CRPropList *list = NULL,
00168                 *result = NULL;
00169 
00170         g_return_val_if_fail (a_this && PRIVATE (a_this)
00171                               && a_prop_name && a_decl, NULL);
00172 
00173         list = cr_prop_list_allocate ();
00174         g_return_val_if_fail (list, NULL);
00175         PRIVATE (list)->prop = a_prop_name;
00176         PRIVATE (list)->decl = a_decl;
00177         result = cr_prop_list_prepend (a_this, list);
00178         return result;
00179 }
00180 
00181 /**
00182  * cr_prop_list_set_prop:
00183  *@a_this: the current instance of #CRPropList
00184  *@a_prop: the property to set
00185  *
00186  *Sets the property of a CRPropList
00187  */
00188 enum CRStatus
00189 cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
00190 {
00191         g_return_val_if_fail (a_this && PRIVATE (a_this)
00192                               && a_prop, CR_BAD_PARAM_ERROR);
00193 
00194         PRIVATE (a_this)->prop = a_prop;
00195         return CR_OK;
00196 }
00197 
00198 /**
00199  * cr_prop_list_get_prop:
00200  *@a_this: the current instance of #CRPropList
00201  *@a_prop: out parameter. The returned property
00202  *
00203  *Getter of the property associated to the current instance
00204  *of #CRPropList
00205  *
00206  *Returns CR_OK upon successful completion, an error code
00207  *otherwise.
00208  */
00209 enum CRStatus
00210 cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
00211 {
00212         g_return_val_if_fail (a_this && PRIVATE (a_this)
00213                               && a_prop, CR_BAD_PARAM_ERROR);
00214 
00215         *a_prop = PRIVATE (a_this)->prop;
00216         return CR_OK;
00217 }
00218 
00219 /**
00220  * cr_prop_list_set_decl:
00221  * @a_this: the current instance of #CRPropList
00222  * @a_decl: the new property value.
00223  *
00224  * Returns CR_OK upon successful completion, an error code otherwise.
00225  */
00226 enum CRStatus
00227 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
00228 {
00229         g_return_val_if_fail (a_this && PRIVATE (a_this)
00230                               && a_decl, CR_BAD_PARAM_ERROR);
00231 
00232         PRIVATE (a_this)->decl = a_decl;
00233         return CR_OK;
00234 }
00235 
00236 /**
00237  * cr_prop_list_get_decl:
00238  * @a_this: the current instance of #CRPropList
00239  * @a_decl: out parameter. The property value
00240  *
00241  * Returns CR_OK upon successful completion.
00242  */
00243 enum CRStatus
00244 cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
00245 {
00246         g_return_val_if_fail (a_this && PRIVATE (a_this)
00247                               && a_decl, CR_BAD_PARAM_ERROR);
00248 
00249         *a_decl = PRIVATE (a_this)->decl;
00250         return CR_OK;
00251 }
00252 
00253 /**
00254  * cr_prop_list_lookup_prop:
00255  *@a_this: the current instance of #CRPropList
00256  *@a_prop: the property to lookup
00257  *@a_prop_list: out parameter. The property/declaration
00258  *pair found (if and only if the function returned code if CR_OK)
00259  *
00260  *Lookup a given property/declaration pair
00261  *
00262  *Returns CR_OK if a prop/decl pair has been found,
00263  *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
00264  *bad happens.
00265  */
00266 enum CRStatus
00267 cr_prop_list_lookup_prop (CRPropList * a_this,
00268                           CRString * a_prop, CRPropList ** a_pair)
00269 {
00270         CRPropList *cur = NULL;
00271 
00272         g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
00273 
00274         if (!a_this)
00275                 return CR_VALUE_NOT_FOUND_ERROR;
00276 
00277         g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00278 
00279         for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
00280                 if (PRIVATE (cur)->prop
00281                     && PRIVATE (cur)->prop->stryng
00282                     && PRIVATE (cur)->prop->stryng->str
00283                     && a_prop->stryng
00284                     && a_prop->stryng->str
00285                     && !strcmp (PRIVATE (cur)->prop->stryng->str, 
00286                                 a_prop->stryng->str))
00287                         break;
00288         }
00289 
00290         if (cur) {
00291                 *a_pair = cur;
00292                 return CR_OK;
00293         }
00294 
00295         return CR_VALUE_NOT_FOUND_ERROR;
00296 }
00297 
00298 /**
00299  * cr_prop_list_get_next:
00300  *@a_this: the current instance of CRPropList
00301  *
00302  *Gets the next prop/decl pair in the list
00303  *
00304  *Returns the next prop/declaration pair of the list, 
00305  *or NULL if we reached end of list (or if an error occurs)
00306  */
00307 CRPropList *
00308 cr_prop_list_get_next (CRPropList * a_this)
00309 {
00310         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
00311 
00312         return PRIVATE (a_this)->next;
00313 }
00314 
00315 /**
00316  * cr_prop_list_get_prev:
00317  *@a_this: the current instance of CRPropList
00318  *
00319  *Gets the previous prop/decl pair in the list
00320  *
00321  *Returns the previous prop/declaration pair of the list, 
00322  *or NULL if we reached end of list (or if an error occurs)
00323  */
00324 CRPropList *
00325 cr_prop_list_get_prev (CRPropList * a_this)
00326 {
00327         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
00328 
00329         return PRIVATE (a_this)->prev;
00330 }
00331 
00332 /**
00333  * cr_prop_list_unlink:
00334  *@a_this: the current list of prop/decl pairs
00335  *@a_pair: the prop/decl pair to unlink.
00336  *
00337  *Unlinks a prop/decl pair from the list
00338  *
00339  *Returns the new list or NULL in case of an error.
00340  */
00341 CRPropList *
00342 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
00343 {
00344         CRPropList *prev = NULL,
00345                 *next = NULL;
00346 
00347         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
00348 
00349         /*some sanity checks */
00350         if (PRIVATE (a_pair)->next) {
00351                 next = PRIVATE (a_pair)->next;
00352                 g_return_val_if_fail (PRIVATE (next), NULL);
00353                 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
00354         }
00355         if (PRIVATE (a_pair)->prev) {
00356                 prev = PRIVATE (a_pair)->prev;
00357                 g_return_val_if_fail (PRIVATE (prev), NULL);
00358                 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
00359         }
00360         if (prev) {
00361                 PRIVATE (prev)->next = next;
00362         }
00363         if (next) {
00364                 PRIVATE (next)->prev = prev;
00365         }
00366         PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
00367         if (a_this == a_pair) {
00368                 if (next)
00369                         return next;
00370                 return NULL;
00371         }
00372         return a_this;
00373 }
00374 
00375 /**
00376  * cr_prop_list_destroy:
00377  * @a_this: the current instance of #CRPropList
00378  */
00379 void
00380 cr_prop_list_destroy (CRPropList * a_this)
00381 {
00382         CRPropList *tail = NULL,
00383                 *cur = NULL;
00384 
00385         g_return_if_fail (a_this && PRIVATE (a_this));
00386 
00387         for (tail = a_this;
00388              tail && PRIVATE (tail) && PRIVATE (tail)->next;
00389              tail = cr_prop_list_get_next (tail)) ;
00390         g_return_if_fail (tail);
00391 
00392         cur = tail;
00393 
00394         while (cur) {
00395                 tail = PRIVATE (cur)->prev;
00396                 if (tail && PRIVATE (tail))
00397                         PRIVATE (tail)->next = NULL;
00398                 PRIVATE (cur)->prev = NULL;
00399                 g_free (PRIVATE (cur));
00400                 PRIVATE (cur) = NULL;
00401                 g_free (cur);
00402                 cur = tail;
00403         }
00404 }