Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

cr-term.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of version 2.1 of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020  * USA
00021  */
00022 
00023 /*
00024  *$Id: cr-term.c,v 1.2 2003/06/20 22:08:50 dodji Exp $
00025  */
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include "cr-term.h"
00029 #include "cr-num.h"
00030 #include "cr-parser.h"
00031 
00032 /**
00033  *@file
00034  *Definition of the #CRTem class.
00035  */
00036 
00037 
00038 static void
00039 cr_term_clear (CRTerm *a_this)
00040 {
00041         g_return_if_fail (a_this) ;
00042 
00043         switch (a_this->type)
00044         {
00045         case TERM_NUMBER:
00046                 if (a_this->content.num)
00047                 {
00048                         cr_num_destroy (a_this->content.num) ;
00049                         a_this->content.num = NULL ;
00050                 }
00051                 break ;
00052 
00053         case TERM_FUNCTION:
00054                 if (a_this->ext_content.func_param)
00055                 {
00056                         cr_term_destroy (a_this->ext_content.func_param) ;
00057                         a_this->ext_content.func_param = NULL ;
00058                 }
00059         case TERM_STRING:
00060         case TERM_IDENT:
00061         case TERM_URI:
00062         case TERM_HASH:
00063                 if (a_this->content.str)
00064                 {
00065                         g_string_free (a_this->content.str, TRUE) ;
00066                         a_this->content.str = NULL ;
00067                 }
00068                 break ;
00069 
00070         case TERM_RGB: 
00071                 if (a_this->content.rgb)
00072                 {
00073                         cr_rgb_destroy (a_this->content.rgb) ;
00074                         a_this->content.rgb = NULL ;
00075                 }
00076                 break ;
00077 
00078         case TERM_UNICODERANGE:
00079         case TERM_NO_TYPE:
00080         default:        
00081                 break ;
00082         }
00083 
00084         a_this->type = TERM_NO_TYPE ;
00085 }
00086 
00087 
00088 /**
00089  *Instanciate a #CRTerm.
00090  *@return the newly build instance
00091  *of #CRTerm.
00092  */
00093 CRTerm *
00094 cr_term_new (void)
00095 {
00096         CRTerm *result = NULL ;
00097 
00098         result = g_try_malloc (sizeof (CRTerm)) ;
00099         if (!result)
00100         {
00101                 cr_utils_trace_info ("Out of memory") ;
00102                 return NULL ;
00103         }
00104         memset (result, 0, sizeof (CRTerm)) ;
00105         return result ;
00106 }
00107 
00108 /**
00109  *Parses an expresion as defined by the css2 spec
00110  *and builds the expression as a list of terms.
00111  *@param a_buf the buffer to parse.
00112  *@return a pointer to the first term of the expression or
00113  *NULL if parsing failed.
00114  */
00115 CRTerm *
00116 cr_term_parse_expression_from_buf (const guchar *a_buf, 
00117                                    enum CREncoding a_encoding)
00118 {
00119         CRParser *parser = NULL ;
00120         CRTerm *result = NULL ;
00121         enum CRStatus status = CR_OK ;
00122 
00123         g_return_val_if_fail (a_buf, NULL) ;
00124 
00125         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
00126                                          a_encoding, FALSE) ;
00127         g_return_val_if_fail (parser, NULL) ;
00128         
00129         status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
00130         if (status != CR_OK)
00131         {
00132                 goto cleanup ;
00133         }
00134 
00135         status = cr_parser_parse_expr (parser, &result) ;
00136         if (status != CR_OK)
00137         {
00138                 if (result)
00139                 {
00140                         cr_term_destroy (result) ;
00141                         result = NULL ;
00142                 }
00143         }
00144 
00145  cleanup:
00146         if (parser)
00147         {
00148                 cr_parser_destroy (parser) ;
00149                 parser = NULL ;
00150         }
00151 
00152         return result ;
00153 }
00154 
00155 enum CRStatus
00156 cr_term_set_number (CRTerm *a_this, CRNum *a_num)
00157 {
00158         g_return_val_if_fail (a_this,
00159                               CR_BAD_PARAM_ERROR) ;
00160 
00161         cr_term_clear (a_this) ;
00162         
00163         a_this->type = TERM_NUMBER ;
00164         a_this->content.num = a_num ;
00165         return CR_OK ;
00166 }
00167 
00168 enum CRStatus
00169 cr_term_set_function (CRTerm *a_this, GString *a_func_name,
00170                       CRTerm *a_func_param)
00171 {
00172         g_return_val_if_fail (a_this,
00173                               CR_BAD_PARAM_ERROR) ;
00174 
00175         cr_term_clear (a_this) ;
00176         
00177         a_this->type = TERM_FUNCTION ;        
00178         a_this->content.str = a_func_name ;
00179         a_this->ext_content.func_param = a_func_param ;
00180         return CR_OK ;
00181 }
00182 
00183 enum CRStatus
00184 cr_term_set_string (CRTerm *a_this, GString *a_str)
00185 {
00186        g_return_val_if_fail (a_this,
00187                               CR_BAD_PARAM_ERROR) ;
00188 
00189        cr_term_clear (a_this) ;
00190         
00191        a_this->type = TERM_STRING ;        
00192        a_this->content.str = a_str ;
00193        return CR_OK ;
00194 }
00195 
00196 enum CRStatus
00197 cr_term_set_ident (CRTerm *a_this, GString *a_str)
00198 {
00199         g_return_val_if_fail (a_this,
00200                               CR_BAD_PARAM_ERROR) ;
00201 
00202         cr_term_clear (a_this) ;
00203         
00204         a_this->type = TERM_IDENT ;        
00205         a_this->content.str = a_str ;
00206         return CR_OK ;
00207 }
00208 
00209 enum CRStatus
00210 cr_term_set_uri (CRTerm *a_this, GString *a_str)
00211 {
00212         g_return_val_if_fail (a_this,
00213                               CR_BAD_PARAM_ERROR) ;
00214 
00215         cr_term_clear (a_this) ;
00216         
00217         a_this->type = TERM_URI ;
00218         a_this->content.str = a_str ;
00219         return CR_OK ;
00220 }
00221         
00222 enum CRStatus
00223 cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb)
00224 {
00225         g_return_val_if_fail (a_this,
00226                               CR_BAD_PARAM_ERROR) ;
00227 
00228        cr_term_clear (a_this) ;
00229         
00230        a_this->type = TERM_RGB ;
00231        a_this->content.rgb = a_rgb ;
00232        return CR_OK ;
00233 }
00234         
00235 enum CRStatus
00236 cr_term_set_hash (CRTerm *a_this, GString *a_str)
00237 {
00238         g_return_val_if_fail (a_this,
00239                               CR_BAD_PARAM_ERROR) ;
00240 
00241         cr_term_clear (a_this) ;
00242         
00243         a_this->type = TERM_HASH ;
00244         a_this->content.str = a_str ;
00245         return CR_OK ;
00246 }
00247 
00248 /**
00249  *Appends a new term to the current list of #CRTerm.
00250  *
00251  *@param a_this the "this pointer" of the current instance
00252  *of #CRTerm .
00253  *@param a_new_term the term to append.
00254  *@return the list of terms with the a_new_term appended to it.
00255  */
00256 CRTerm *
00257 cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term)
00258 {
00259         CRTerm *cur = NULL ;
00260 
00261         g_return_val_if_fail (a_new_term, 
00262                               NULL) ;
00263         
00264         if (a_this == NULL)
00265                 return a_new_term ;
00266 
00267         for (cur = a_this ;cur->next ; cur = cur->next) ;
00268         
00269         cur->next = a_new_term ;
00270         a_new_term->prev = cur ;
00271 
00272         return a_this ;
00273 }
00274 
00275 
00276 /**
00277  *Prepends a term to the list of terms represented by a_this.
00278  *
00279  *@param a_this the "this pointer" of the current instance of
00280  *#CRTerm .
00281  *@param a_new_term the term to prepend.
00282  *@return the head of the new list.
00283  */
00284 CRTerm *
00285 cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term)
00286 {
00287         g_return_val_if_fail (a_this && a_new_term, 
00288                               NULL) ;
00289         
00290         a_new_term->next = a_this ;
00291         a_this->prev = a_new_term ;
00292         
00293         return a_new_term ;
00294 }
00295 
00296 
00297 /**
00298  *Serializes the expression represented by
00299  *the chained instances of #CRterm.
00300  *@param a_this the current instance of #CRTerm
00301  *@return the zero terminated string containing the serialized
00302  *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
00303  */
00304 guchar *
00305 cr_term_to_string (CRTerm *a_this)
00306 {
00307         GString *str_buf = NULL ;
00308         CRTerm *cur =  NULL ;
00309         guchar *result = NULL, *content = NULL ;
00310 
00311         g_return_val_if_fail (a_this, NULL) ;
00312 
00313         str_buf = g_string_new (NULL) ;
00314         g_return_val_if_fail (str_buf, NULL) ;
00315 
00316         for (cur = a_this ; cur ; cur = cur->next)
00317         {
00318                 if ((cur->content.str == NULL)
00319                     && (cur->content.num == NULL)
00320                     && (cur->content.str == NULL)
00321                     && (cur->content.rgb == NULL))
00322                         continue ;
00323                 
00324                 switch (cur->operator)
00325                 {
00326                 case DIVIDE:
00327                         g_string_append_printf (str_buf, " / ") ;
00328                         break ;
00329 
00330                 case COMMA:
00331                         g_string_append_printf (str_buf, ", ") ;
00332                         break ;
00333 
00334                 case NO_OP:
00335                         if (cur->prev)
00336                         {
00337                                 g_string_append_printf (str_buf, " ") ;
00338                         }
00339                         break ;
00340                 default:
00341                         
00342                         break ;
00343                 }
00344 
00345                 switch (cur->unary_op)
00346                 {
00347                 case PLUS_UOP:
00348                         g_string_append_printf (str_buf, "+") ;
00349                         break ;
00350 
00351                 case MINUS_UOP:
00352                         g_string_append_printf (str_buf, "-") ;
00353                         break ;
00354 
00355                 default :
00356                         break ;
00357                 }
00358 
00359                 switch (cur->type)
00360                 {
00361                 case TERM_NUMBER:
00362                         if (cur->content.num)
00363                         {
00364                                 content = 
00365                                         cr_num_to_string 
00366                                         (cur->content.num) ;
00367                         }
00368 
00369                         if (content)
00370                         {
00371                                 g_string_append(str_buf, content) ;
00372                                 g_free (content) ;
00373                                 content = NULL ;
00374                         }
00375 
00376                         break ;
00377 
00378                 case TERM_FUNCTION:
00379                         if (cur->content.str)
00380                         {
00381                                 content = g_strndup 
00382                                         (cur->content.str->str,
00383                                          cur->content.str->len) ;
00384                         }                        
00385 
00386                         if (content)
00387                         {
00388                                 g_string_append_printf (str_buf, "%s(", 
00389                                                         content) ;
00390 
00391                                 if (a_this->ext_content.func_param)
00392                                 {
00393                                         guchar *tmp_str = NULL ;
00394 
00395                                         tmp_str = cr_term_to_string 
00396                                                 (a_this->
00397                                                  ext_content.func_param);
00398 
00399                                         if (tmp_str)
00400                                         { 
00401                                                 g_string_append_printf 
00402                                                         (str_buf, 
00403                                                          "%s",
00404                                                          tmp_str) ;
00405                                                 g_free (tmp_str) ;
00406                                                 tmp_str = NULL ;
00407                                         }
00408 
00409                                         g_string_append_printf (str_buf, 
00410                                                                 ")") ;
00411                                         g_free (content) ;
00412                                         content = NULL ;
00413                                 }
00414                         }
00415 
00416                         break ;
00417 
00418                 case TERM_STRING:
00419                         if (cur->content.str)
00420                         {
00421                                 content = g_strndup 
00422                                         (cur->content.str->str,
00423                                          cur->content.str->len) ;
00424                         }
00425 
00426                         if (content)
00427                         {
00428                                 g_string_append_printf (str_buf, 
00429                                                         "\"%s\"", 
00430                                                         content) ;
00431                                 g_free (content) ;
00432                                 content = NULL ;
00433                         }                        
00434                         break ;
00435 
00436                 case TERM_IDENT:
00437                         if (cur->content.str)
00438                         {
00439                                 content = g_strndup 
00440                                 (cur->content.str->str,
00441                                  cur->content.str->len) ;
00442                         }
00443                         
00444                         if (content)
00445                         {
00446                                 g_string_append (str_buf,content) ;
00447                                 g_free (content) ;
00448                                 content = NULL ;
00449                         }                        
00450                         break ;
00451 
00452                 case TERM_URI:
00453                         if (cur->content.str)
00454                         {
00455                                 content = g_strndup 
00456                                 (cur->content.str->str,
00457                                  cur->content.str->len) ;
00458                         }
00459 
00460                         if (content)
00461                         {
00462                                 g_string_append_printf 
00463                                         (str_buf,  "url(%s)",content) ;
00464                                 g_free (content) ;
00465                                 content = NULL ;
00466                         }                        
00467                         break ;
00468 
00469                 case TERM_RGB:
00470                         if (cur->content.rgb)
00471                         {
00472                                 guchar *tmp_str = NULL ;
00473 
00474                                 g_string_append_printf (str_buf,  "rgb(");
00475                                 tmp_str = cr_rgb_to_string 
00476                                         (cur->content.rgb) ;
00477 
00478                                 if (tmp_str)
00479                                 {
00480                                         g_string_append (str_buf,
00481                                                          tmp_str) ;
00482                                         g_free (tmp_str) ;
00483                                         tmp_str = NULL ;
00484                                 }
00485                                 g_string_append_printf (str_buf,  ")") ;
00486                         }
00487 
00488                         break ;
00489 
00490                 case TERM_UNICODERANGE:
00491                         g_string_append_printf 
00492                                 (str_buf, 
00493                                  "?found unicoderange: dump not supported yet?") ;
00494                         break ;
00495 
00496                 case TERM_HASH:
00497                         if (cur->content.str)
00498                         {
00499                                 content = g_strndup 
00500                                         (cur->content.str->str,
00501                                          cur->content.str->len) ;
00502                         }
00503 
00504                         if (content)
00505                         {
00506                                 g_string_append_printf (str_buf, 
00507                                                         "#%s", content) ;
00508                                 g_free (content) ;
00509                                 content = NULL ;
00510                         }
00511                         break ;
00512 
00513                 default:
00514                         g_string_append_printf (str_buf, 
00515                                                 "%s", 
00516                                                 "Unrecognized Term type");
00517                         break ;
00518                 }
00519         }
00520 
00521         if (str_buf)
00522         {
00523                 result = str_buf->str ;
00524                 g_string_free (str_buf, FALSE) ;
00525                 str_buf = NULL ;
00526         }
00527 
00528         return result ;
00529 }
00530 
00531 /**
00532  *Dumps the expression (a list of terms connected by operators)
00533  *to a file.
00534  *TODO: finish the dump. The dump of some type of terms have not yet been
00535  *implemented.
00536  *@param a_this the current instance of #CRTerm.
00537  *@param a_fp the destination file pointer.
00538  */
00539 void
00540 cr_term_dump (CRTerm *a_this, FILE *a_fp)
00541 {
00542         guchar *content=NULL ;
00543 
00544         g_return_if_fail (a_this) ;
00545 
00546         content = cr_term_to_string (a_this) ;
00547 
00548         if (content)
00549         {
00550                 fprintf (a_fp, "%s", content) ;
00551                 g_free (content) ;
00552         }
00553 }
00554 
00555 
00556 /**
00557  *Increments the reference counter of the current instance
00558  *of #CRTerm.*
00559  *@param a_this the current instance of #CRTerm.
00560  */
00561 void
00562 cr_term_ref (CRTerm *a_this)
00563 {
00564         g_return_if_fail (a_this) ;
00565 
00566         a_this->ref_count ++ ;
00567 }
00568 
00569 
00570 /**
00571  *Decrements the ref count of the current instance of
00572  *#CRTerm. If the ref count reaches zero, the instance is
00573  *destroyed.
00574  *@param a_this the current instance of #CRTerm.
00575  *@return TRUE if the current instance has been destroyed, FALSE otherwise.
00576  */
00577 gboolean
00578 cr_term_unref (CRTerm *a_this)
00579 {
00580         g_return_val_if_fail (a_this, FALSE) ;
00581 
00582         if (a_this->ref_count)
00583         {
00584                 a_this->ref_count -- ;
00585         }
00586 
00587         if (a_this->ref_count == 0)
00588         {
00589                 cr_term_destroy (a_this) ;
00590                 return TRUE ;
00591         }
00592 
00593         return FALSE ;
00594 }
00595 
00596 /**
00597  *The destructor of the the #CRTerm class.
00598  *@param a_this the "this pointer" of the current instance
00599  *of #CRTerm.
00600  */
00601 void
00602 cr_term_destroy (CRTerm *a_this)
00603 {
00604         g_return_if_fail (a_this) ;
00605 
00606         cr_term_clear (a_this) ;
00607 
00608         if (a_this->next)
00609         {
00610                 cr_term_destroy (a_this->next) ;
00611                 a_this->next = NULL ;
00612         }
00613 
00614         if (a_this)
00615         {
00616                 g_free (a_this) ;
00617         }
00618 
00619 }

Generated on Wed Oct 1 01:36:49 2003 for Libcroco by doxygen 1.3.3