Libcroco
|
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 *occured 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 }