cr-declaration.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of version 2.1 of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00018  * USA
00019  *
00020  * Author: Dodji Seketeli.
00021  * See COPYRIGHTS file for copyright information.
00022  */
00023 
00024 
00025 #include <string.h>
00026 #include "cr-declaration.h"
00027 #include "cr-statement.h"
00028 #include "cr-parser.h"
00029 
00030 /**
00031  *@CRDeclaration:
00032  *
00033  *The definition of the #CRDeclaration class.
00034  */
00035 
00036 /**
00037  * dump:
00038  *@a_this: the current instance of #CRDeclaration.
00039  *@a_fp: the destination file pointer.
00040  *@a_indent: the number of indentation white char. 
00041  *
00042  *Dumps (serializes) one css declaration to a file.
00043  */
00044 static void
00045 dump (CRDeclaration * a_this, FILE * a_fp, glong a_indent)
00046 {
00047         guchar *str = NULL;
00048 
00049         g_return_if_fail (a_this);
00050 
00051         str = cr_declaration_to_string (a_this, a_indent);
00052         if (str) {
00053                 fprintf (a_fp, "%s", str);
00054                 g_free (str);
00055                 str = NULL;
00056         }
00057 }
00058 
00059 /**
00060  * cr_declaration_new:
00061  * @a_statement: the statement this declaration belongs to. can be NULL.
00062  *@a_property: the property string of the declaration
00063  *@a_value: the value expression of the declaration.
00064  *Constructor of #CRDeclaration.
00065  *
00066  *Returns the newly built instance of #CRDeclaration, or NULL in
00067  *case of error.
00068  */
00069 CRDeclaration *
00070 cr_declaration_new (CRStatement * a_statement,
00071                     CRString * a_property, CRTerm * a_value)
00072 {
00073         CRDeclaration *result = NULL;
00074 
00075         g_return_val_if_fail (a_property, NULL);
00076 
00077         if (a_statement)
00078                 g_return_val_if_fail (a_statement
00079                                       && ((a_statement->type == RULESET_STMT)
00080                                           || (a_statement->type
00081                                               == AT_FONT_FACE_RULE_STMT)
00082                                           || (a_statement->type
00083                                               == AT_PAGE_RULE_STMT)), NULL);
00084 
00085         result = g_try_malloc (sizeof (CRDeclaration));
00086         if (!result) {
00087                 cr_utils_trace_info ("Out of memory");
00088                 return NULL;
00089         }
00090         memset (result, 0, sizeof (CRDeclaration));
00091         result->property = a_property;
00092         result->value = a_value;
00093 
00094         if (a_value) {
00095                 cr_term_ref (a_value);
00096         }
00097         result->parent_statement = a_statement;
00098         return result;
00099 }
00100 
00101 /**
00102  * cr_declaration_parse_from_buf:
00103  *@a_statement: the parent css2 statement of this
00104  *this declaration. Must be non NULL and of type
00105  *RULESET_STMT (must be a ruleset).
00106  *@a_str: the string that contains the statement.
00107  *@a_enc: the encoding of a_str.
00108  *
00109  *Parses a text buffer that contains
00110  *a css declaration.
00111  *Returns the parsed declaration, or NULL in case of error.
00112  */
00113 CRDeclaration *
00114 cr_declaration_parse_from_buf (CRStatement * a_statement,
00115                                const guchar * a_str, enum CREncoding a_enc)
00116 {
00117         enum CRStatus status = CR_OK;
00118         CRTerm *value = NULL;
00119         CRString *property = NULL;
00120         CRDeclaration *result = NULL;
00121         CRParser *parser = NULL;
00122         gboolean important = FALSE;
00123 
00124         g_return_val_if_fail (a_str, NULL);
00125         if (a_statement)
00126                 g_return_val_if_fail (a_statement->type == RULESET_STMT,
00127                                       NULL);
00128 
00129         parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE);
00130         g_return_val_if_fail (parser, NULL);
00131 
00132         status = cr_parser_try_to_skip_spaces_and_comments (parser);
00133         if (status != CR_OK)
00134                 goto cleanup;
00135 
00136         status = cr_parser_parse_declaration (parser, &property,
00137                                               &value, &important);
00138         if (status != CR_OK || !property)
00139                 goto cleanup;
00140 
00141         result = cr_declaration_new (a_statement, property, value);
00142         if (result) {
00143                 property = NULL;
00144                 value = NULL;
00145                 result->important = important;
00146         }
00147 
00148       cleanup:
00149 
00150         if (parser) {
00151                 cr_parser_destroy (parser);
00152                 parser = NULL;
00153         }
00154 
00155         if (property) {
00156                 cr_string_destroy (property);
00157                 property = NULL;
00158         }
00159 
00160         if (value) {
00161                 cr_term_destroy (value);
00162                 value = NULL;
00163         }
00164 
00165         return result;
00166 }
00167 
00168 /**
00169  * cr_declaration_parse_list_from_buf:
00170  *@a_str: the input buffer that contains the list of declaration to
00171  *parse.
00172  *@a_enc: the encoding of a_str
00173  *
00174  *Parses a ';' separated list of properties declaration.
00175  *Returns the parsed list of declaration, NULL if parsing failed.
00176  */
00177 CRDeclaration *
00178 cr_declaration_parse_list_from_buf (const guchar * a_str,
00179                                     enum CREncoding a_enc)
00180 {
00181 
00182         enum CRStatus status = CR_OK;
00183         CRTerm *value = NULL;
00184         CRString *property = NULL;
00185         CRDeclaration *result = NULL,
00186                 *cur_decl = NULL;
00187         CRParser *parser = NULL;
00188         CRTknzr *tokenizer = NULL;
00189         gboolean important = FALSE;
00190 
00191         g_return_val_if_fail (a_str, NULL);
00192 
00193         parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE);
00194         g_return_val_if_fail (parser, NULL);
00195         status = cr_parser_get_tknzr (parser, &tokenizer);
00196         if (status != CR_OK || !tokenizer) {
00197                 if (status == CR_OK)
00198                         status = CR_ERROR;
00199                 goto cleanup;
00200         }
00201         status = cr_parser_try_to_skip_spaces_and_comments (parser);
00202         if (status != CR_OK)
00203                 goto cleanup;
00204 
00205         status = cr_parser_parse_declaration (parser, &property,
00206                                               &value, &important);
00207         if (status != CR_OK || !property) {
00208                 if (status != CR_OK)
00209                         status = CR_ERROR;
00210                 goto cleanup;
00211         }
00212         result = cr_declaration_new (NULL, property, value);
00213         if (result) {
00214                 property = NULL;
00215                 value = NULL;
00216                 result->important = important;
00217         }
00218         /*now, go parse the other declarations */
00219         for (;;) {
00220                 guint32 c = 0;
00221 
00222                 cr_parser_try_to_skip_spaces_and_comments (parser);
00223                 status = cr_tknzr_peek_char (tokenizer, &c);
00224                 if (status != CR_OK) {
00225                         if (status == CR_END_OF_INPUT_ERROR)
00226                                 status = CR_OK;
00227                         goto cleanup;
00228                 }
00229                 if (c == ';') {
00230                         status = cr_tknzr_read_char (tokenizer, &c);
00231                 } else {
00232                         break;
00233                 }
00234                 important = FALSE;
00235                 cr_parser_try_to_skip_spaces_and_comments (parser);
00236                 status = cr_parser_parse_declaration (parser, &property,
00237                                                       &value, &important);
00238                 if (status != CR_OK || !property) {
00239                         if (status == CR_END_OF_INPUT_ERROR) {
00240                                 status = CR_OK;
00241                         }
00242                         break;
00243                 }
00244                 cur_decl = cr_declaration_new (NULL, property, value);
00245                 if (cur_decl) {
00246                         cur_decl->important = important;
00247                         result = cr_declaration_append (result, cur_decl);
00248                         property = NULL;
00249                         value = NULL;
00250                         cur_decl = NULL;
00251                 } else {
00252                         break;
00253                 }
00254         }
00255 
00256       cleanup:
00257 
00258         if (parser) {
00259                 cr_parser_destroy (parser);
00260                 parser = NULL;
00261         }
00262 
00263         if (property) {
00264                 cr_string_destroy (property);
00265                 property = NULL;
00266         }
00267 
00268         if (value) {
00269                 cr_term_destroy (value);
00270                 value = NULL;
00271         }
00272 
00273         if (status != CR_OK && result) {
00274                 cr_declaration_destroy (result);
00275                 result = NULL;
00276         }
00277         return result;
00278 }
00279 
00280 /**
00281  * cr_declaration_append:
00282  *@a_this: the current declaration list.
00283  *@a_new: the declaration to append.
00284  *
00285  *Appends a new declaration to the current declarations list.
00286  *Returns the declaration list with a_new appended to it, or NULL
00287  *in case of error.
00288  */
00289 CRDeclaration *
00290 cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
00291 {
00292         CRDeclaration *cur = NULL;
00293 
00294         g_return_val_if_fail (a_new, NULL);
00295 
00296         if (!a_this)
00297                 return a_new;
00298 
00299         for (cur = a_this; cur && cur->next; cur = cur->next) ;
00300 
00301         cur->next = a_new;
00302         a_new->prev = cur;
00303 
00304         return a_this;
00305 }
00306 
00307 /**
00308  * cr_declaration_unlink:
00309  *@a_decls: the declaration to unlink.
00310  *
00311  *Unlinks the declaration from the declaration list.
00312  *case of a successfull completion, NULL otherwise.
00313  *
00314  *Returns a pointer to the unlinked declaration in
00315  */
00316 CRDeclaration *
00317 cr_declaration_unlink (CRDeclaration * a_decl)
00318 {
00319         CRDeclaration *result = a_decl;
00320 
00321         g_return_val_if_fail (result, NULL);
00322 
00323         /*
00324          *some sanity checks first
00325          */
00326         if (a_decl->prev) {
00327                 g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
00328 
00329         }
00330         if (a_decl->next) {
00331                 g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
00332         }
00333 
00334         /*
00335          *now, the real unlinking job.
00336          */
00337         if (a_decl->prev) {
00338                 a_decl->prev->next = a_decl->next;
00339         }
00340         if (a_decl->next) {
00341                 a_decl->next->prev = a_decl->prev;
00342         }
00343         if (a_decl->parent_statement) {
00344                 CRDeclaration **children_decl_ptr = NULL;
00345 
00346                 switch (a_decl->parent_statement->type) {
00347                 case RULESET_STMT:
00348                         if (a_decl->parent_statement->kind.ruleset) {
00349                                 children_decl_ptr =
00350                                         &a_decl->parent_statement->
00351                                         kind.ruleset->decl_list;
00352                         }
00353 
00354                         break;
00355 
00356                 case AT_FONT_FACE_RULE_STMT:
00357                         if (a_decl->parent_statement->kind.font_face_rule) {
00358                                 children_decl_ptr =
00359                                         &a_decl->parent_statement->
00360                                         kind.font_face_rule->decl_list;
00361                         }
00362                         break;
00363                 case AT_PAGE_RULE_STMT:
00364                         if (a_decl->parent_statement->kind.page_rule) {
00365                                 children_decl_ptr =
00366                                         &a_decl->parent_statement->
00367                                         kind.page_rule->decl_list;
00368                         }
00369 
00370                 default:
00371                         break;
00372                 }
00373                 if (children_decl_ptr
00374                     && *children_decl_ptr && *children_decl_ptr == a_decl)
00375                         *children_decl_ptr = (*children_decl_ptr)->next;
00376         }
00377 
00378         a_decl->next = NULL;
00379         a_decl->prev = NULL;
00380         a_decl->parent_statement = NULL;
00381 
00382         return result;
00383 }
00384 
00385 /**
00386  * cr_declaration_prepend:
00387  * @a_this: the current declaration list.
00388  * @a_new: the declaration to prepend.
00389  *
00390  * prepends a declaration to the current declaration list.
00391  *
00392  * Returns the list with a_new prepended or NULL in case of error.
00393  */
00394 CRDeclaration *
00395 cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
00396 {
00397         CRDeclaration *cur = NULL;
00398 
00399         g_return_val_if_fail (a_new, NULL);
00400 
00401         if (!a_this)
00402                 return a_new;
00403 
00404         a_this->prev = a_new;
00405         a_new->next = a_this;
00406 
00407         for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
00408 
00409         return cur;
00410 }
00411 
00412 /**
00413  * cr_declaration_append2:
00414  *@a_this: the current declaration list.
00415  *@a_prop: the property string of the declaration to append.
00416  *@a_value: the value of the declaration to append.
00417  *
00418  *Appends a declaration to the current declaration list.
00419  *Returns the list with the new property appended to it, or NULL in
00420  *case of an error.
00421  */
00422 CRDeclaration *
00423 cr_declaration_append2 (CRDeclaration * a_this,
00424                         CRString * a_prop, CRTerm * a_value)
00425 {
00426         CRDeclaration *new_elem = NULL;
00427 
00428         if (a_this) {
00429                 new_elem = cr_declaration_new (a_this->parent_statement,
00430                                                a_prop, a_value);
00431         } else {
00432                 new_elem = cr_declaration_new (NULL, a_prop, a_value);
00433         }
00434 
00435         g_return_val_if_fail (new_elem, NULL);
00436 
00437         return cr_declaration_append (a_this, new_elem);
00438 }
00439 
00440 /**
00441  * cr_declaration_dump:
00442  *@a_this: the current instance of #CRDeclaration.
00443  *@a_fp: the destination file.
00444  *@a_indent: the number of indentation white char.
00445  *@a_one_per_line: whether to put one declaration per line of not .
00446  *
00447  *
00448  *Dumps a declaration list to a file.
00449  */
00450 void
00451 cr_declaration_dump (CRDeclaration * a_this, FILE * a_fp, glong a_indent,
00452                      gboolean a_one_per_line)
00453 {
00454         CRDeclaration *cur = NULL;
00455 
00456         g_return_if_fail (a_this);
00457 
00458         for (cur = a_this; cur; cur = cur->next) {
00459                 if (cur->prev) {
00460                         if (a_one_per_line == TRUE)
00461                                 fprintf (a_fp, ";\n");
00462                         else
00463                                 fprintf (a_fp, "; ");
00464                 }
00465                 dump (cur, a_fp, a_indent);
00466         }
00467 }
00468 
00469 /**
00470  * cr_declaration_dump_one:
00471  *@a_this: the current instance of #CRDeclaration.
00472  *@a_fp: the destination file.
00473  *@a_indent: the number of indentation white char.
00474  *
00475  *Dumps the first declaration of the declaration list to a file.
00476  */
00477 void
00478 cr_declaration_dump_one (CRDeclaration * a_this, FILE * a_fp, glong a_indent)
00479 {
00480         g_return_if_fail (a_this);
00481 
00482         dump (a_this, a_fp, a_indent);
00483 }
00484 
00485 /**
00486  * cr_declaration_to_string:
00487  *@a_this: the current instance of #CRDeclaration.
00488  *@a_indent: the number of indentation white char
00489  *to put before the actual serialisation.
00490  *
00491  *Serializes the declaration into a string
00492  *Returns the serialized form the declaration. The caller must
00493  *free the string using g_free().
00494  */
00495 gchar *
00496 cr_declaration_to_string (CRDeclaration * a_this, gulong a_indent)
00497 {
00498         GString *stringue = NULL;
00499 
00500         guchar *str = NULL,
00501                 *result = NULL;
00502 
00503         g_return_val_if_fail (a_this, NULL);
00504 
00505         stringue = g_string_new (NULL);
00506 
00507         if (a_this->property 
00508             && a_this->property->stryng
00509             && a_this->property->stryng->str) {
00510                 str = g_strndup (a_this->property->stryng->str,
00511                                  a_this->property->stryng->len);
00512                 if (str) {
00513                         cr_utils_dump_n_chars2 (' ', stringue, 
00514                                                 a_indent);
00515                         g_string_append (stringue, str);
00516                         g_free (str);
00517                         str = NULL;
00518                 } else
00519                         goto error;
00520 
00521                 if (a_this->value) {
00522                         guchar *value_str = NULL;
00523 
00524                         value_str = cr_term_to_string (a_this->value);
00525                         if (value_str) {
00526                                 g_string_append_printf (stringue, " : %s",
00527                                                         value_str);
00528                                 g_free (value_str);
00529                         } else
00530                                 goto error;
00531                 }
00532                 if (a_this->important == TRUE) {
00533                         g_string_append_printf (stringue, " %s",
00534                                                 "!important");
00535                 }
00536         }
00537         if (stringue && stringue->str) {
00538                 result = stringue->str;
00539                 g_string_free (stringue, FALSE);
00540         }
00541         return result;
00542 
00543       error:
00544         if (stringue) {
00545                 g_string_free (stringue, TRUE);
00546                 stringue = NULL;
00547         }
00548         if (str) {
00549                 g_free (str);
00550                 str = NULL;
00551         }
00552 
00553         return result;
00554 }
00555 
00556 /**
00557  * cr_declaration_list_to_string:
00558  *@a_this: the current instance of #CRDeclaration.
00559  *@a_indent: the number of indentation white char
00560  *to put before the actual serialisation.
00561  *
00562  *Serializes the declaration list into a string
00563  */
00564 guchar *
00565 cr_declaration_list_to_string (CRDeclaration * a_this, gulong a_indent)
00566 {
00567         CRDeclaration *cur = NULL;
00568         GString *stringue = NULL;
00569         guchar *str = NULL,
00570                 *result = NULL;
00571 
00572         g_return_val_if_fail (a_this, NULL);
00573 
00574         stringue = g_string_new (NULL);
00575 
00576         for (cur = a_this; cur; cur = cur->next) {
00577                 str = cr_declaration_to_string (cur, a_indent);
00578                 if (str) {
00579                         g_string_append_printf (stringue, "%s;", str);
00580                         g_free (str);
00581                 } else
00582                         break;
00583         }
00584         if (stringue && stringue->str) {
00585                 result = stringue->str;
00586                 g_string_free (stringue, FALSE);
00587         }
00588 
00589         return result;
00590 }
00591 
00592 /**
00593  * cr_declaration_list_to_string2:
00594  *@a_this: the current instance of #CRDeclaration.
00595  *@a_indent: the number of indentation white char
00596  @a_one_decl_per_line: whether to output one doc per line or not.
00597  *to put before the actual serialisation.
00598  *
00599  *Serializes the declaration list into a string
00600  *Returns the serialized form the declararation.
00601  */
00602 guchar *
00603 cr_declaration_list_to_string2 (CRDeclaration * a_this,
00604                                 gulong a_indent, gboolean a_one_decl_per_line)
00605 {
00606         CRDeclaration *cur = NULL;
00607         GString *stringue = NULL;
00608         guchar *str = NULL,
00609                 *result = NULL;
00610 
00611         g_return_val_if_fail (a_this, NULL);
00612 
00613         stringue = g_string_new (NULL);
00614 
00615         for (cur = a_this; cur; cur = cur->next) {
00616                 str = cr_declaration_to_string (cur, a_indent);
00617                 if (str) {
00618                         if (a_one_decl_per_line == TRUE) {
00619                                 if (cur->next)
00620                                         g_string_append_printf (stringue,
00621                                                                 "%s;\n", str);
00622                                 else
00623                                         g_string_append (stringue,
00624                                                          str);
00625                         } else {
00626                                 if (cur->next)
00627                                         g_string_append_printf (stringue,
00628                                                                 "%s;", str);
00629                                 else
00630                                         g_string_append (stringue,
00631                                                          str);
00632                         }
00633                         g_free (str);
00634                 } else
00635                         break;
00636         }
00637         if (stringue && stringue->str) {
00638                 result = stringue->str;
00639                 g_string_free (stringue, FALSE);
00640         }
00641 
00642         return result;
00643 }
00644 
00645 /**
00646  * cr_declaration_nr_props:
00647  *@a_this: the current instance of #CRDeclaration.
00648  *Return the number of properties in the declaration
00649  */
00650 gint
00651 cr_declaration_nr_props (CRDeclaration * a_this)
00652 {
00653         CRDeclaration *cur = NULL;
00654         int nr = 0;
00655 
00656         g_return_val_if_fail (a_this, -1);
00657 
00658         for (cur = a_this; cur; cur = cur->next)
00659                 nr++;
00660         return nr;
00661 }
00662 
00663 /**
00664  * cr_declaration_get_from_list:
00665  *@a_this: the current instance of #CRDeclaration.
00666  *@itemnr: the index into the declaration list.
00667  *
00668  *Use an index to get a CRDeclaration from the declaration list.
00669  *
00670  *Returns #CRDeclaration at position itemnr, 
00671  *if itemnr > number of declarations - 1,
00672  *it will return NULL.
00673  */
00674 CRDeclaration *
00675 cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
00676 {
00677         CRDeclaration *cur = NULL;
00678         int nr = 0;
00679 
00680         g_return_val_if_fail (a_this, NULL);
00681 
00682         for (cur = a_this; cur; cur = cur->next)
00683                 if (nr++ == itemnr)
00684                         return cur;
00685         return NULL;
00686 }
00687 
00688 /**
00689  * cr_declaration_get_by_prop_name:
00690  *@a_this: the current instance of #CRDeclaration.
00691  *@a_prop: the property name to search for.
00692  *
00693  *Use property name to get a CRDeclaration from the declaration list.
00694  *Returns #CRDeclaration with property name a_prop, or NULL if not found.
00695  */
00696 CRDeclaration *
00697 cr_declaration_get_by_prop_name (CRDeclaration * a_this,
00698                                  const guchar * a_prop)
00699 {
00700         CRDeclaration *cur = NULL;
00701 
00702         g_return_val_if_fail (a_this, NULL);
00703         g_return_val_if_fail (a_prop, NULL);
00704 
00705         for (cur = a_this; cur; cur = cur->next) {
00706                 if (cur->property 
00707                     && cur->property->stryng
00708                     && cur->property->stryng->str) {
00709                         if (!strcmp (cur->property->stryng->str, 
00710                                      a_prop)) {
00711                                 return cur;
00712                         }
00713                 }
00714         }
00715         return NULL;
00716 }
00717 
00718 /**
00719  * cr_declaration_ref:
00720  *@a_this: the current instance of #CRDeclaration.
00721  *
00722  *Increases the ref count of the current instance of #CRDeclaration.
00723  */
00724 void
00725 cr_declaration_ref (CRDeclaration * a_this)
00726 {
00727         g_return_if_fail (a_this);
00728 
00729         a_this->ref_count++;
00730 }
00731 
00732 /**
00733  * cr_declaration_unref:
00734  *@param a_this the current instance of #CRDeclaration.
00735  *@return TRUE if the current instance of #CRDeclaration has been destroyed
00736  *(ref count reached zero), FALSE otherwise.
00737  *
00738  *Decrements the ref count of the current instance of #CRDeclaration.
00739  *If the ref count reaches zero, the current instance of #CRDeclaration
00740  *if destroyed.
00741  *Returns TRUE if the object got destroyed, FALSE otherwise.
00742  */
00743 gboolean
00744 cr_declaration_unref (CRDeclaration * a_this)
00745 {
00746         g_return_val_if_fail (a_this, FALSE);
00747 
00748         if (a_this->ref_count) {
00749                 a_this->ref_count--;
00750         }
00751 
00752         if (a_this->ref_count == 0) {
00753                 cr_declaration_destroy (a_this);
00754                 return TRUE;
00755         }
00756         return FALSE;
00757 }
00758 
00759 /**
00760  * cr_declaration_destroy:
00761  *@a_this: the current instance of #CRDeclaration.
00762  *
00763  *Destructor of the declaration list.
00764  */
00765 void
00766 cr_declaration_destroy (CRDeclaration * a_this)
00767 {
00768         CRDeclaration *cur = NULL;
00769 
00770         g_return_if_fail (a_this);
00771 
00772         /*
00773          *Go get the tail of the list.
00774          *Meanwhile, free each property/value pair contained in the list.
00775          */
00776         for (cur = a_this; cur && cur->next; cur = cur->next) {
00777                 if (cur->property) {
00778                         cr_string_destroy (cur->property);
00779                         cur->property = NULL;
00780                 }
00781 
00782                 if (cur->value) {
00783                         cr_term_destroy (cur->value);
00784                         cur->value = NULL;
00785                 }
00786         }
00787 
00788         if (cur) {
00789                 if (cur->property) {
00790                         cr_string_destroy (cur->property);
00791                         cur->property = NULL;
00792                 }
00793 
00794                 if (cur->value) {
00795                         cr_term_destroy (cur->value);
00796                         cur->value = NULL;
00797                 }
00798         }
00799 
00800         /*in case the list contains only one element */
00801         if (cur && !cur->prev) {
00802                 g_free (cur);
00803                 return;
00804         }
00805 
00806         /*walk backward the list and free each "next" element */
00807         for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
00808                 if (cur->next) {
00809                         g_free (cur->next);
00810                         cur->next = NULL;
00811                 }
00812         }
00813 
00814         if (!cur)
00815                 return;
00816 
00817         if (cur->next) {
00818                 g_free (cur->next);
00819                 cur->next = NULL;
00820         }
00821 
00822         g_free (cur);
00823 }

Generated on Wed Mar 15 18:23:54 2006 for Libcroco by  doxygen 1.4.6