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