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

src/main/mxml-node.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: mxml-node.c,v 1.6 2004/04/27 23:23:47 rlk Exp $"
00003  *
00004  * Node support code for mini-XML, a small XML-like file parsing library.
00005  *
00006  * Copyright 2003 by Michael Sweet.
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Library General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * Contents:
00019  *
00020  *   stp_mxmlAdd()        - Add a node to a tree.
00021  *   stp_mxmlDelete()     - Delete a node and all of its children.
00022  *   stp_mxmlNewElement() - Create a new element node.
00023  *   stp_mxmlNewInteger() - Create a new integer node.
00024  *   stp_mxmlNewOpaque()  - Create a new opaque string.
00025  *   stp_mxmlNewReal()    - Create a new real number node.
00026  *   stp_mxmlNewText()    - Create a new text fragment node.
00027  *   stp_mxmlRemove()     - Remove a node from its parent.
00028  *   mxml_new()       - Create a new node.
00029  */
00030 
00031 /*
00032  * Include necessary headers...
00033  */
00034 
00035 #include <gimp-print/mxml.h>
00036 #include "config.h"
00037 
00038 
00039 /*
00040  * Local functions...
00041  */
00042 
00043 static stp_mxml_node_t  *mxml_new(stp_mxml_node_t *parent, stp_mxml_type_t type);
00044 
00045 
00046 /*
00047  * 'stp_mxmlAdd()' - Add a node to a tree.
00048  *
00049  * Adds the specified node to the parent. If the child argument is not
00050  * NULL, puts the new node before or after the specified child depending
00051  * on the value of the where argument. If the child argument is NULL,
00052  * puts the new node at the beginning of the child list (STP_MXML_ADD_BEFORE)
00053  * or at the end of the child list (STP_MXML_ADD_AFTER). The constant
00054  * STP_MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
00055  */
00056 
00057 void
00058 stp_mxmlAdd(stp_mxml_node_t *parent,            /* I - Parent node */
00059         int         where,              /* I - Where to add, STP_MXML_ADD_BEFORE or STP_MXML_ADD_AFTER */
00060         stp_mxml_node_t *child,         /* I - Child node for where or STP_MXML_ADD_TO_PARENT */
00061         stp_mxml_node_t *node)          /* I - Node to add */
00062 {
00063 /*  fprintf(stderr, "stp_mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
00064          where, child, node);*/
00065 
00066  /*
00067   * Range check input...
00068   */
00069 
00070   if (!parent || !node)
00071     return;
00072 
00073  /*
00074   * Remove the node from any existing parent...
00075   */
00076 
00077   if (node->parent)
00078     stp_mxmlRemove(node);
00079 
00080  /*
00081   * Reset pointers...
00082   */
00083 
00084   node->parent = parent;
00085 
00086   switch (where)
00087   {
00088     case STP_MXML_ADD_BEFORE :
00089         if (!child || child == parent->child || child->parent != parent)
00090         {
00091          /*
00092           * Insert as first node under parent...
00093           */
00094 
00095           node->next = parent->child;
00096 
00097           if (parent->child)
00098             parent->child->prev = node;
00099           else
00100             parent->last_child = node;
00101 
00102           parent->child = node;
00103         }
00104         else
00105         {
00106          /*
00107           * Insert node before this child...
00108           */
00109 
00110           node->next = child;
00111           node->prev = child->prev;
00112 
00113           if (child->prev)
00114             child->prev->next = node;
00115           else
00116             parent->child = node;
00117 
00118           child->prev = node;
00119         }
00120         break;
00121 
00122     case STP_MXML_ADD_AFTER :
00123         if (!child || child == parent->last_child || child->parent != parent)
00124         {
00125          /*
00126           * Insert as last node under parent...
00127           */
00128 
00129           node->parent = parent;
00130           node->prev   = parent->last_child;
00131 
00132           if (parent->last_child)
00133             parent->last_child->next = node;
00134           else
00135             parent->child = node;
00136 
00137           parent->last_child = node;
00138         }
00139         else
00140         {
00141          /*
00142           * Insert node after this child...
00143           */
00144 
00145           node->prev = child;
00146           node->next = child->next;
00147 
00148           if (child->next)
00149             child->next->prev = node;
00150           else
00151             parent->last_child = node;
00152 
00153           child->next = node;
00154         }
00155         break;
00156   }
00157 }
00158 
00159 
00160 /*
00161  * 'stp_mxmlDelete()' - Delete a node and all of its children.
00162  *
00163  * If the specified node has a parent, this function first removes the
00164  * node from its parent using the stp_mxmlRemove() function.
00165  */
00166 
00167 void
00168 stp_mxmlDelete(stp_mxml_node_t *node)           /* I - Node to delete */
00169 {
00170   int   i;                              /* Looping var */
00171 
00172 
00173 /*  fprintf(stderr, "stp_mxmlDelete(node=%p)\n", node);*/
00174 
00175  /*
00176   * Range check input...
00177   */
00178 
00179   if (!node)
00180     return;
00181 
00182  /*
00183   * Remove the node from its parent, if any...
00184   */
00185 
00186   stp_mxmlRemove(node);
00187 
00188  /*
00189   * Delete children...
00190   */
00191 
00192   while (node->child)
00193     stp_mxmlDelete(node->child);
00194 
00195  /*
00196   * Now delete any node data...
00197   */
00198 
00199   switch (node->type)
00200   {
00201     case STP_MXML_ELEMENT :
00202         if (node->value.element.name)
00203           free(node->value.element.name);
00204 
00205         if (node->value.element.num_attrs)
00206         {
00207           for (i = 0; i < node->value.element.num_attrs; i ++)
00208           {
00209             if (node->value.element.attrs[i].name)
00210               free(node->value.element.attrs[i].name);
00211             if (node->value.element.attrs[i].value)
00212               free(node->value.element.attrs[i].value);
00213           }
00214 
00215           free(node->value.element.attrs);
00216         }
00217         break;
00218     case STP_MXML_INTEGER :
00219        /* Nothing to do */
00220         break;
00221     case STP_MXML_OPAQUE :
00222         if (node->value.opaque)
00223           free(node->value.opaque);
00224         break;
00225     case STP_MXML_REAL :
00226        /* Nothing to do */
00227         break;
00228     case STP_MXML_TEXT :
00229         if (node->value.text.string)
00230           free(node->value.text.string);
00231         break;
00232   }
00233 
00234  /*
00235   * Free this node...
00236   */
00237 
00238   free(node);
00239 }
00240 
00241 
00242 /*
00243  * 'stp_mxmlNewElement()' - Create a new element node.
00244  *
00245  * The new element node is added to the end of the specified parent's child
00246  * list. The constant STP_MXML_NO_PARENT can be used to specify that the new
00247  * element node has no parent.
00248  */
00249 
00250 stp_mxml_node_t *                               /* O - New node */
00251 stp_mxmlNewElement(stp_mxml_node_t *parent,     /* I - Parent node or STP_MXML_NO_PARENT */
00252                const char  *name)       /* I - Name of element */
00253 {
00254   stp_mxml_node_t       *node;                  /* New node */
00255 
00256 
00257  /*
00258   * Range check input...
00259   */
00260 
00261   if (!name)
00262     return (NULL);
00263 
00264  /*
00265   * Create the node and set the element name...
00266   */
00267 
00268   if ((node = mxml_new(parent, STP_MXML_ELEMENT)) != NULL)
00269     node->value.element.name = strdup(name);
00270 
00271   return (node);
00272 }
00273 
00274 
00275 /*
00276  * 'stp_mxmlNewInteger()' - Create a new integer node.
00277  *
00278  * The new integer node is added to the end of the specified parent's child
00279  * list. The constant STP_MXML_NO_PARENT can be used to specify that the new
00280  * integer node has no parent.
00281  */
00282 
00283 stp_mxml_node_t *                               /* O - New node */
00284 stp_mxmlNewInteger(stp_mxml_node_t *parent,     /* I - Parent node or STP_MXML_NO_PARENT */
00285                int         integer)     /* I - Integer value */
00286 {
00287   stp_mxml_node_t       *node;                  /* New node */
00288 
00289 
00290  /*
00291   * Range check input...
00292   */
00293 
00294   if (!parent)
00295     return (NULL);
00296 
00297  /*
00298   * Create the node and set the element name...
00299   */
00300 
00301   if ((node = mxml_new(parent, STP_MXML_INTEGER)) != NULL)
00302     node->value.integer = integer;
00303 
00304   return (node);
00305 }
00306 
00307 
00308 /*
00309  * 'stp_mxmlNewOpaque()' - Create a new opaque string.
00310  *
00311  * The new opaque node is added to the end of the specified parent's child
00312  * list. The constant STP_MXML_NO_PARENT can be used to specify that the new
00313  * opaque node has no parent. The opaque string must be nul-terminated and
00314  * is copied into the new node.
00315  */
00316 
00317 stp_mxml_node_t *                               /* O - New node */
00318 stp_mxmlNewOpaque(stp_mxml_node_t *parent,      /* I - Parent node or STP_MXML_NO_PARENT */
00319               const char  *opaque)      /* I - Opaque string */
00320 {
00321   stp_mxml_node_t       *node;                  /* New node */
00322 
00323 
00324  /*
00325   * Range check input...
00326   */
00327 
00328   if (!parent || !opaque)
00329     return (NULL);
00330 
00331  /*
00332   * Create the node and set the element name...
00333   */
00334 
00335   if ((node = mxml_new(parent, STP_MXML_OPAQUE)) != NULL)
00336     node->value.opaque = strdup(opaque);
00337 
00338   return (node);
00339 }
00340 
00341 
00342 /*
00343  * 'stp_mxmlNewReal()' - Create a new real number node.
00344  *
00345  * The new real number node is added to the end of the specified parent's
00346  * child list. The constant STP_MXML_NO_PARENT can be used to specify that
00347  * the new real number node has no parent.
00348  */
00349 
00350 stp_mxml_node_t *                               /* O - New node */
00351 stp_mxmlNewReal(stp_mxml_node_t *parent,        /* I - Parent node or STP_MXML_NO_PARENT */
00352             double      real)           /* I - Real number value */
00353 {
00354   stp_mxml_node_t       *node;                  /* New node */
00355 
00356 
00357  /*
00358   * Range check input...
00359   */
00360 
00361   if (!parent)
00362     return (NULL);
00363 
00364  /*
00365   * Create the node and set the element name...
00366   */
00367 
00368   if ((node = mxml_new(parent, STP_MXML_REAL)) != NULL)
00369     node->value.real = real;
00370 
00371   return (node);
00372 }
00373 
00374 
00375 /*
00376  * 'stp_mxmlNewText()' - Create a new text fragment node.
00377  *
00378  * The new text node is added to the end of the specified parent's child
00379  * list. The constant STP_MXML_NO_PARENT can be used to specify that the new
00380  * text node has no parent. The whitespace parameter is used to specify
00381  * whether leading whitespace is present before the node. The text
00382  * string must be nul-terminated and is copied into the new node.  
00383  */
00384 
00385 stp_mxml_node_t *                               /* O - New node */
00386 stp_mxmlNewText(stp_mxml_node_t *parent,        /* I - Parent node or STP_MXML_NO_PARENT */
00387             int         whitespace,     /* I - 1 = leading whitespace, 0 = no whitespace */
00388             const char  *string)        /* I - String */
00389 {
00390   stp_mxml_node_t       *node;                  /* New node */
00391 
00392 
00393  /*
00394   * Range check input...
00395   */
00396 
00397   if (!parent || !string)
00398     return (NULL);
00399 
00400  /*
00401   * Create the node and set the text value...
00402   */
00403 
00404   if ((node = mxml_new(parent, STP_MXML_TEXT)) != NULL)
00405   {
00406     node->value.text.whitespace = whitespace;
00407     node->value.text.string     = strdup(string);
00408   }
00409 
00410   return (node);
00411 }
00412 
00413 
00414 /*
00415  * 'stp_mxmlRemove()' - Remove a node from its parent.
00416  *
00417  * Does not free memory used by the node - use stp_mxmlDelete() for that.
00418  * This function does nothing if the node has no parent.
00419  */
00420 
00421 void
00422 stp_mxmlRemove(stp_mxml_node_t *node)           /* I - Node to remove */
00423 {
00424  /*
00425   * Range check input...
00426   */
00427 
00428 /*  fprintf(stderr, "stp_mxmlRemove(node=%p)\n", node);*/
00429 
00430   if (!node || !node->parent)
00431     return;
00432 
00433  /*
00434   * Remove from parent...
00435   */
00436 
00437   if (node->prev)
00438     node->prev->next = node->next;
00439   else
00440     node->parent->child = node->next;
00441 
00442   if (node->next)
00443     node->next->prev = node->prev;
00444   else
00445     node->parent->last_child = node->prev;
00446 
00447   node->parent = NULL;
00448   node->prev   = NULL;
00449   node->next   = NULL;
00450 }
00451 
00452 
00453 /*
00454  * 'mxml_new()' - Create a new node.
00455  */
00456 
00457 static stp_mxml_node_t *                        /* O - New node */
00458 mxml_new(stp_mxml_node_t *parent,               /* I - Parent node */
00459          stp_mxml_type_t type)          /* I - Node type */
00460 {
00461   stp_mxml_node_t       *node;                  /* New node */
00462 
00463 
00464  /*
00465   * Allocate memory for the node...
00466   */
00467 
00468   if ((node = calloc(1, sizeof(stp_mxml_node_t))) == NULL)
00469     return (NULL);
00470 
00471  /*
00472   * Set the node type...
00473   */
00474 
00475   node->type = type;
00476 
00477  /*
00478   * Add to the parent if present...
00479   */
00480 
00481   if (parent)
00482     stp_mxmlAdd(parent, STP_MXML_ADD_AFTER, STP_MXML_ADD_TO_PARENT, node);
00483 
00484  /*
00485   * Return the new node...
00486   */
00487 
00488   return (node);
00489 }
00490 
00491 
00492 /*
00493  * End of "$Id: mxml-node.c,v 1.6 2004/04/27 23:23:47 rlk Exp $".
00494  */

Generated on Wed Aug 25 07:56:14 2004 for libgimpprint API Reference by doxygen 1.3.6