1/* 2 * This file is part of The Croco Library 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of version 2.1 of the GNU General Public 6 * License as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 16 * USA 17 * 18 * Author: Dodji Seketeli 19 * See COPYRIGHTS file for copyrights information. 20 */ 21 22#include <config.h> 23#include <string.h> 24#include "cr-prop-list.h" 25 26#define PRIVATE(a_obj) (a_obj)->priv 27 28struct _CRPropListPriv { 29 CRString *prop; 30 CRDeclaration *decl; 31 CRPropList *next; 32 CRPropList *prev; 33}; 34 35static CRPropList *cr_prop_list_allocate (void); 36 37/** 38 *Default allocator of CRPropList 39 *@return the newly allocated CRPropList or NULL 40 *if an error arises. 41 */ 42static CRPropList * 43cr_prop_list_allocate (void) 44{ 45 CRPropList *result = NULL; 46 47 result = g_try_malloc (sizeof (CRPropList)); 48 if (!result) { 49 cr_utils_trace_info ("could not allocate CRPropList"); 50 return NULL; 51 } 52 memset (result, 0, sizeof (CRPropList)); 53 PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv)); 54 if (!result) { 55 cr_utils_trace_info ("could not allocate CRPropListPriv"); 56 g_free (result); 57 return NULL; 58 } 59 memset (PRIVATE (result), 0, sizeof (CRPropListPriv)); 60 return result; 61} 62 63/**************** 64 *public methods 65 ***************/ 66 67/** 68 * cr_prop_list_append: 69 *@a_this: the current instance of #CRPropList 70 *@a_to_append: the property list to append 71 * 72 *Appends a property list to the current one. 73 * 74 *Returns the resulting prop list, or NULL if an error 75 *occured 76 */ 77CRPropList * 78cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append) 79{ 80 CRPropList *cur = NULL; 81 82 g_return_val_if_fail (a_to_append, NULL); 83 84 if (!a_this) 85 return a_to_append; 86 87 /*go fetch the last element of the list */ 88 for (cur = a_this; 89 cur && PRIVATE (cur) && PRIVATE (cur)->next; 90 cur = PRIVATE (cur)->next) ; 91 g_return_val_if_fail (cur, NULL); 92 PRIVATE (cur)->next = a_to_append; 93 PRIVATE (a_to_append)->prev = cur; 94 return a_this; 95} 96 97/** 98 * cr_prop_list_append2: 99 *Appends a pair of prop/declaration to 100 *the current prop list. 101 *@a_this: the current instance of #CRPropList 102 *@a_prop: the property to consider 103 *@a_decl: the declaration to consider 104 *Returns the resulting property list, or NULL in case 105 *of an error. 106 */ 107CRPropList * 108cr_prop_list_append2 (CRPropList * a_this, 109 CRString * a_prop, 110 CRDeclaration * a_decl) 111{ 112 CRPropList *list = NULL, 113 *result = NULL; 114 115 g_return_val_if_fail (a_prop && a_decl, NULL); 116 117 list = cr_prop_list_allocate (); 118 g_return_val_if_fail (list && PRIVATE (list), NULL); 119 120 PRIVATE (list)->prop = a_prop; 121 PRIVATE (list)->decl = a_decl; 122 123 result = cr_prop_list_append (a_this, list); 124 return result; 125} 126 127/** 128 * cr_prop_list_prepend: 129 *@a_this: the current instance of #CRPropList 130 *@a_to_prepend: the new list to prepend. 131 * 132 *Prepends a list to the current list 133 *Returns the new properties list. 134 */ 135CRPropList * 136cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend) 137{ 138 CRPropList *cur = NULL; 139 140 g_return_val_if_fail (a_to_prepend, NULL); 141 142 if (!a_this) 143 return a_to_prepend; 144 145 for (cur = a_to_prepend; cur && PRIVATE (cur)->next; 146 cur = PRIVATE (cur)->next) ; 147 g_return_val_if_fail (cur, NULL); 148 PRIVATE (cur)->next = a_this; 149 PRIVATE (a_this)->prev = cur; 150 return a_to_prepend; 151} 152 153/** 154 * cr_prop_list_prepend2: 155 *@a_this: the current instance of #CRPropList 156 *@a_prop_name: property name to append 157 *@a_decl: the property value to append. 158 * 159 *Prepends a propertie to a list of properties 160 * 161 * Returns the new property list. 162 */ 163CRPropList * 164cr_prop_list_prepend2 (CRPropList * a_this, 165 CRString * a_prop_name, CRDeclaration * a_decl) 166{ 167 CRPropList *list = NULL, 168 *result = NULL; 169 170 g_return_val_if_fail (a_this && PRIVATE (a_this) 171 && a_prop_name && a_decl, NULL); 172 173 list = cr_prop_list_allocate (); 174 g_return_val_if_fail (list, NULL); 175 PRIVATE (list)->prop = a_prop_name; 176 PRIVATE (list)->decl = a_decl; 177 result = cr_prop_list_prepend (a_this, list); 178 return result; 179} 180 181/** 182 * cr_prop_list_set_prop: 183 *@a_this: the current instance of #CRPropList 184 *@a_prop: the property to set 185 * 186 *Sets the property of a CRPropList 187 */ 188enum CRStatus 189cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop) 190{ 191 g_return_val_if_fail (a_this && PRIVATE (a_this) 192 && a_prop, CR_BAD_PARAM_ERROR); 193 194 PRIVATE (a_this)->prop = a_prop; 195 return CR_OK; 196} 197 198/** 199 * cr_prop_list_get_prop: 200 *@a_this: the current instance of #CRPropList 201 *@a_prop: out parameter. The returned property 202 * 203 *Getter of the property associated to the current instance 204 *of #CRPropList 205 * 206 *Returns CR_OK upon successful completion, an error code 207 *otherwise. 208 */ 209enum CRStatus 210cr_prop_list_get_prop (CRPropList * a_this, CRString ** a_prop) 211{ 212 g_return_val_if_fail (a_this && PRIVATE (a_this) 213 && a_prop, CR_BAD_PARAM_ERROR); 214 215 *a_prop = PRIVATE (a_this)->prop; 216 return CR_OK; 217} 218 219/** 220 * cr_prop_list_set_decl: 221 * @a_this: the current instance of #CRPropList 222 * @a_decl: the new property value. 223 * Returns CR_OK upon successful completion, an error code otherwise. 224 */ 225enum CRStatus 226cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl) 227{ 228 g_return_val_if_fail (a_this && PRIVATE (a_this) 229 && a_decl, CR_BAD_PARAM_ERROR); 230 231 PRIVATE (a_this)->decl = a_decl; 232 return CR_OK; 233} 234 235/** 236 * cr_prop_list_get_decl: 237 * @a_this: the current instance of #CRPropList 238 * @a_decl: out parameter. The property value 239 * Returns CR_OK upon successful completion. 240 */ 241enum CRStatus 242cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl) 243{ 244 g_return_val_if_fail (a_this && PRIVATE (a_this) 245 && a_decl, CR_BAD_PARAM_ERROR); 246 247 *a_decl = PRIVATE (a_this)->decl; 248 return CR_OK; 249} 250 251/** 252 * cr_prop_list_lookup_prop: 253 *@a_this: the current instance of #CRPropList 254 *@a_prop: the property to lookup 255 *@a_prop_list: out parameter. The property/declaration 256 *pair found (if and only if the function returned code if CR_OK) 257 * 258 *Lookup a given property/declaration pair 259 * 260 *Returns CR_OK if a prop/decl pair has been found, 261 *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something 262 *bad happens. 263 */ 264enum CRStatus 265cr_prop_list_lookup_prop (CRPropList * a_this, 266 CRString * a_prop, CRPropList ** a_pair) 267{ 268 CRPropList *cur = NULL; 269 270 g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR); 271 272 if (!a_this) 273 return CR_VALUE_NOT_FOUND_ERROR; 274 275 g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR); 276 277 for (cur = a_this; cur; cur = PRIVATE (cur)->next) { 278 if (PRIVATE (cur)->prop 279 && PRIVATE (cur)->prop->stryng 280 && PRIVATE (cur)->prop->stryng->str 281 && a_prop->stryng 282 && a_prop->stryng->str 283 && !strcmp (PRIVATE (cur)->prop->stryng->str, 284 a_prop->stryng->str)) 285 break; 286 } 287 288 if (cur) { 289 *a_pair = cur; 290 return CR_OK; 291 } 292 293 return CR_VALUE_NOT_FOUND_ERROR; 294} 295 296/** 297 * cr_prop_list_get_next: 298 *@a_this: the current instance of CRPropList 299 * 300 *Gets the next prop/decl pair in the list 301 * 302 *Returns the next prop/declaration pair of the list, 303 *or NULL if we reached end of list (or if an error occurs) 304 */ 305CRPropList * 306cr_prop_list_get_next (CRPropList * a_this) 307{ 308 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL); 309 310 return PRIVATE (a_this)->next; 311} 312 313/** 314 * cr_prop_list_get_prev: 315 *@a_this: the current instance of CRPropList 316 * 317 *Gets the previous prop/decl pair in the list 318 * 319 *Returns the previous prop/declaration pair of the list, 320 *or NULL if we reached end of list (or if an error occurs) 321 */ 322CRPropList * 323cr_prop_list_get_prev (CRPropList * a_this) 324{ 325 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL); 326 327 return PRIVATE (a_this)->prev; 328} 329 330/** 331 * cr_prop_list_unlink: 332 *@a_this: the current list of prop/decl pairs 333 *@a_pair: the prop/decl pair to unlink. 334 * 335 *Unlinks a prop/decl pair from the list 336 * 337 *Returns the new list or NULL in case of an error. 338 */ 339CRPropList * 340cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair) 341{ 342 CRPropList *prev = NULL, 343 *next = NULL; 344 345 g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL); 346 347 /*some sanity checks */ 348 if (PRIVATE (a_pair)->next) { 349 next = PRIVATE (a_pair)->next; 350 g_return_val_if_fail (PRIVATE (next), NULL); 351 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL); 352 } 353 if (PRIVATE (a_pair)->prev) { 354 prev = PRIVATE (a_pair)->prev; 355 g_return_val_if_fail (PRIVATE (prev), NULL); 356 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL); 357 } 358 if (prev) { 359 PRIVATE (prev)->next = next; 360 } 361 if (next) { 362 PRIVATE (next)->prev = prev; 363 } 364 PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL; 365 if (a_this == a_pair) { 366 if (next) 367 return next; 368 return NULL; 369 } 370 return a_this; 371} 372 373/** 374 * cr_prop_list_detroy: 375 * @a_this: the current instance of #CRPropList 376 */ 377void 378cr_prop_list_destroy (CRPropList * a_this) 379{ 380 CRPropList *tail = NULL, 381 *cur = NULL; 382 383 g_return_if_fail (a_this && PRIVATE (a_this)); 384 385 for (tail = a_this; 386 tail && PRIVATE (tail) && PRIVATE (tail)->next; 387 tail = cr_prop_list_get_next (tail)) ; 388 g_return_if_fail (tail); 389 390 cur = tail; 391 392 while (cur) { 393 tail = PRIVATE (cur)->prev; 394 if (tail && PRIVATE (tail)) 395 PRIVATE (tail)->next = NULL; 396 PRIVATE (cur)->prev = NULL; 397 g_free (PRIVATE (cur)); 398 PRIVATE (cur) = NULL; 399 g_free (cur); 400 cur = tail; 401 } 402} 403