Annotation of gpl/axl/src/axl_node.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  *  LibAxl:  Another XML library
                      3:  *  Copyright (C) 2006 Advanced Software Production Line, S.L.
                      4:  *
                      5:  *  This program is free software; you can redistribute it and/or
                      6:  *  modify it under the terms of the GNU Lesser General Public License
                      7:  *  as published by the Free Software Foundation; either version 2.1 of
                      8:  *  the License, or (at your option) any later version.
                      9:  *
                     10:  *  This program is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
                     13:  *  GNU Lesser General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU Lesser General Public
                     16:  *  License along with this program; if not, write to the Free
                     17:  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
                     18:  *  02111-1307 USA
                     19:  *  
                     20:  *  You may find a copy of the license under this software is released
                     21:  *  at COPYING file. This is LGPL software: you are welcome to
                     22:  *  develop proprietary applications using this library without any
                     23:  *  royalty or fee but returning back any change, improvement or
                     24:  *  addition in the form of source code, project image, documentation
                     25:  *  patches, etc. 
                     26:  *
                     27:  *  For commercial support on build XML enabled solutions contact us:
                     28:  *          
                     29:  *      Postal address:
                     30:  *         Advanced Software Production Line, S.L.
                     31:  *         Edificio Alius A, Oficina 102,
                     32:  *         C/ Antonio Suarez Nº 10,
                     33:  *         Alcalá de Henares 28802 Madrid
                     34:  *         Spain
                     35:  *
                     36:  *      Email address:
                     37:  *         info@aspl.es - http://www.aspl.es/xml
                     38:  */
                     39: 
                     40: #include <axl.h>
                     41: #define LOG_DOMAIN "axl-node"
                     42: 
                     43: /**
                     44:  * \defgroup axl_node_module Axl Node: Xml node interface functions to use and manipulate xml nodes inside documents.
                     45:  */
                     46: 
                     47: /** 
                     48:  * \addtogroup axl_node_module
                     49:  * @{
                     50:  */
                     51: 
                     52: struct _axlAttrCursor {
                     53:        axlPointer     data;
                     54:        int            count;
                     55:        axlNode      * node;
                     56: };
                     57: 
                     58: /** 
                     59:  * @internal Axl content representation used to store comments, xml
                     60:  * content, CDATA content and entity references.
                     61:  */
                     62: typedef struct _axlNodeContent axlNodeContent;
                     63: 
                     64: struct _axlNodeContent {
                     65:        /** 
                     66:         * @internal
                     67:         *
                     68:         * @brief Pointer which holds current content inside the xml
                     69:         * node.
                     70:         */
                     71:        char          * content;
                     72:        /** 
                     73:         * @internal
                     74:         *
                     75:         * @brief Current content size stored on the given axlNode.
                     76:         */
                     77:        int             content_size;
                     78:        
                     79: };
                     80: 
                     81: /** 
                     82:  * @internal Type representation to hold node attributes while they
                     83:  * are fewer.
                     84:  */
                     85: typedef struct _axlNodeAttr axlNodeAttr;
                     86: 
                     87: struct _axlNodeAttr {
                     88:        /** 
                     89:         * @internal Node attribute name.
                     90:         */
                     91:        char        * attribute;
                     92: 
                     93:        /** 
                     94:         * @internal Node attribute value.
                     95:         */
                     96:        char        * value;
                     97: 
                     98:        /** 
                     99:         * @internal Flags the attribute pair to be considered from a
                    100:         * factory.
                    101:         */
                    102:        axl_bool          from_factory;
                    103: 
                    104:        /** 
                    105:         * @internal Next attribute.
                    106:         */
                    107:        axlNodeAttr * next;
                    108: };
                    109: 
                    110: /** 
                    111:  * @internal Function that allows to copy all attributes found on the
                    112:  * list received.
                    113:  * 
                    114:  * @param list The attribute list to copy.
                    115:  * 
                    116:  * @return A newly allocated attribute list.
                    117:  */
                    118: axlNodeAttr * __axl_node_copy_attr_list (axlNodeAttr * list)
                    119: {
                    120:        axlNodeAttr * result   = NULL;
                    121: 
                    122:        /* if the list isn't defined, return NULL */
                    123:        if (list == NULL)
                    124:                return NULL;
                    125: 
                    126:        /* alloc memory to hold attribute name and value, and
                    127:         * copy it from the list */
                    128:        result             = axl_new (axlNodeAttr, 1);
1.1.1.2 ! misho     129:        /* check allocated result */
        !           130:        if (result == NULL)
        !           131:                return NULL;
1.1       misho     132:        result->attribute  = axl_strdup (list->attribute);
                    133:        result->value      = axl_strdup (list->value);
                    134: 
                    135:        /* call to copy the rest of the list */
                    136:        result->next = __axl_node_copy_attr_list (list->next);
                    137: 
                    138:        /* return result created */
                    139:        return result;
                    140: }
                    141: 
                    142: /** 
                    143:  * @internal Deallocs the attribute list received.
                    144:  * 
                    145:  * @param list The attribute list to copy.
                    146:  * 
                    147:  * @return A newly allocated attribute list.
                    148:  */
                    149: void __axl_node_free_attr_list (axlNodeAttr * attr)
                    150: {
                    151:        axlNodeAttr * next;
                    152: 
                    153:        /* if the list isn't defined, return NULL */
                    154:        if (attr == NULL)
                    155:                return;
                    156: 
                    157:        /* copy all nodes */
                    158:        while (attr != NULL) {
                    159:                /* get the next attribute */
                    160:                next = attr->next;
                    161: 
                    162:                /* free attribute description */
                    163:                if (! attr->from_factory) {
                    164:                        axl_free (attr->attribute);
                    165:                        axl_free (attr->value);
                    166:                        axl_free (attr);
                    167:                } /* end if */
                    168: 
                    169:                /* get the next */
                    170:                attr = next;
                    171:                
                    172:        } /* end while */
                    173: 
                    174:        /* return result created */
                    175:        return;
                    176: }
                    177: 
                    178: /** 
                    179:  * @internal Function that allows to now if both lists represents the
                    180:  * same set of attributes, even if they aren't ordered using the same.
                    181:  * 
                    182:  * @param attr The first attribute pointing to the rest of the
                    183:  * attribute list.
                    184:  *
                    185:  * @param attr2 The second attribute pointing to the rest of the
                    186:  * attribute list.
                    187:  * 
                    188:  * @return \ref axl_true if both lists are equal, otherwise \ref axl_false is
                    189:  * returned.
                    190:  */
                    191: axl_bool __axl_node_attr_list_is_equal (axlNodeAttr * attr, axlNodeAttr * attr2)
                    192: {
                    193:        axlNodeAttr * attrAux;
                    194:        axl_bool      found;
                    195: 
                    196:        /* for each attribute found in the attribute list, check it on
                    197:         * the second list */
                    198:        while (attr != NULL) {
                    199:                
                    200:                attrAux = attr2;
                    201:                found   = axl_false;
                    202:                while (attrAux != NULL) {
                    203:                        
                    204:                        /* check attribute */
                    205:                        if (axl_cmp (attrAux->attribute, attr->attribute) &&
                    206:                            axl_cmp (attrAux->value, attr->value)) {
                    207:                                /* attribute found, break the loop */
                    208:                                found = axl_true;
                    209:                                break;
                    210:                        }
                    211: 
                    212:                        /* next attribute */
                    213:                        attrAux = attrAux->next;
                    214:                        
                    215:                } /* end while */
                    216:                
                    217:                /* check if the attribute was found */
                    218:                if (! found )
                    219:                        return axl_false;
                    220: 
                    221:                /* get the next */
                    222:                attr = attr->next;
                    223:                
                    224:        } /* end while */
                    225: 
                    226:        /* all attributes was found, including its values, so, the
                    227:         * list is equal */
                    228:        return axl_true;
                    229: }
                    230: 
                    231: typedef enum {
                    232:        /** 
                    233:         * @internal Signal axl library that the node was allocated by
                    234:         * a factory not by the system alloc.
                    235:         */
                    236:        NODE_FROM_FACTORY      = 1,
                    237: 
                    238:        /** 
                    239:         * @internal Signal axl library that the node node was
                    240:         * allocated by a factory not by the system alloc.
                    241:         */
                    242:        NODE_NAME_FROM_FACTORY = 1 << 2
                    243: } axlNodeConf;
                    244: 
                    245: struct _axlNode {
                    246:        /** 
                    247:         * @internal
                    248:         *
                    249:         * Node name that is the value found at the very begining of
                    250:         * the node definition <name.../>
                    251:         */
                    252:        char          * name;
                    253: 
                    254:        /** 
                    255:         * @internal Number of attributes stored. This value is used
                    256:         * to now if the attributes are stored using a hash or a
                    257:         * linked list. In the case it is equal or greater than 11, a
                    258:         * hash is used to store attribute. Otherwise, a linked list
                    259:         * (using axlAttrNode) is used.
                    260:         */
                    261:        int             attr_num;
                    262: 
                    263:        /** 
                    264:         * @internal
                    265:         * @brief The attributes this node has.
                    266:         */
                    267:        axlPointer    * attributes;
                    268: 
                    269:        /** 
                    270:         * @internal A reference to the first child.
                    271:         */
                    272:        axlItem      * first;
                    273: 
                    274:        /** 
                    275:         * @internal A reference to the last child.
                    276:         */
                    277:        axlItem      * last;
                    278: 
                    279:        /** 
                    280:         * @internal A hash used to store arbitrary data associated to
                    281:         * the node.
                    282:         */
                    283:        axlHash       * annotate_data; 
                    284: 
                    285:        /** 
                    286:         * @internal Internal reference to the holder axlItem
                    287:         * containing the axl node reference.
                    288:         */
                    289:        axlItem       * holder;
                    290:        
                    291:        /** 
                    292:         * @internal Value that contains flags for configuration.
                    293:         */
                    294:        int             conf;
                    295: };
                    296: 
                    297: struct _axlItem {
                    298:        /** 
                    299:         * @internal A reference to the type that is being hold by the
                    300:         * encapsulation reference.
                    301:         */
                    302:        AxlItemType     type;
                    303:        
                    304:        /** 
                    305:         * @internal The reference to the pointer that is actually
                    306:         * stored.
                    307:         */
                    308:        axlPointer      data;
                    309: 
                    310:        /** 
                    311:         * @internal
                    312:         * A pointer to the parent node.
                    313:         */
                    314:        axlNode       * parent;
                    315: 
                    316:        /** 
                    317:         * @internal
                    318:         *
                    319:         * A pointer to the brother node, the node that is found on
                    320:         * the next position.
                    321:         */
                    322:        axlItem       * next;
                    323: 
                    324:        /** 
                    325:         * @internal Stores a reference to the previous node inside
                    326:         * the same level.
                    327:         */
                    328:        axlItem       * previous;
                    329: 
                    330:        /** 
                    331:         * @internal
                    332:         *
                    333:         * Internal reference to the whole xml document where the node
                    334:         * is contained.
                    335:         */
                    336:        axlDoc        * doc;
                    337: };
                    338: 
                    339: /** 
                    340:  * @internal
                    341:  *
                    342:  * @brief Internal position function which ensures that nodes added
                    343:  * will be added at the end of the list.
                    344:  */
                    345: int __axl_node_equal (axlPointer a, axlPointer b)
                    346: {
                    347:        return 1;
                    348: }
                    349: 
                    350: /** 
                    351:  * @internal
                    352:  *
                    353:  * Internal function which allocates the enough memory to copy
                    354:  * received content changing all escape sequences.
                    355:  */
                    356: char * __axl_node_content_copy_and_escape (const char * content, 
                    357:                                           int          content_size, 
                    358:                                           int          additional_size,
                    359:                                           axl_bool     cdata)
                    360: {
                    361:        int    iterator  = 0;
                    362:        int    iterator2 = 0;
                    363:        char * result;
                    364:        axl_return_val_if_fail (content, NULL);
                    365: 
                    366:        /* allocate the memory to be returned */
                    367:        result = axl_new (char, content_size + additional_size + 1);
                    368: 
                    369:        /* iterate over all content defined */
                    370:        while (iterator2 < content_size) {
                    371:                /* check for &apos; */
                    372:                if (content [iterator2] == '\'') {
                    373:                        memcpy (result + iterator, "&apos;", 6);
                    374:                        iterator += 6;
                    375:                        iterator2++;
                    376:                        continue;
                    377:                }
                    378: 
                    379:                /* check for &quot; */
                    380:                if (content [iterator2] == '"') {
                    381:                        memcpy (result + iterator, "&quot;", 6);
                    382:                        iterator += 6;
                    383:                        iterator2++;
                    384:                        continue;
                    385:                }
                    386: 
                    387:                /* check for &amp; */
                    388:                if (content [iterator2] == '&') {
                    389:                        memcpy (result + iterator, "&amp;", 5);
                    390:                        iterator += 5;
                    391:                        iterator2++;
                    392:                        continue;
                    393:                }
                    394: 
                    395:                /* check for &gt; */
                    396:                if (content [iterator2] == '>') {
                    397:                        memcpy (result + iterator, "&gt;", 4);
                    398:                        iterator += 4;
                    399:                        iterator2++;
                    400:                        continue;
                    401:                }
                    402: 
                    403:                /* check for &lt; */
                    404:                if (content [iterator2] == '<') {
                    405:                        memcpy (result + iterator, "&lt;", 4);
                    406:                        iterator += 4;
                    407:                        iterator2++;
                    408:                        continue;
                    409:                }
                    410: 
                    411:                /* check for ]]> declaration */
                    412:                if (content [iterator2] == ']' && content [iterator2 + 1] == ']' && content [iterator2 + 2] == '>') {
                    413:                        if (cdata) {
                    414:                                memcpy (result + iterator, "]]>]]&gt;<![CDATA[", 18);
                    415:                                iterator  += 18;
                    416:                                iterator2 +=3;
                    417:                        } else {
                    418:                                memcpy (result + iterator, "]]&gt;", 6);
                    419:                                iterator  += 6;
                    420:                                iterator2 += 3;
                    421:                        }
                    422:                        continue;
                    423:                }
                    424: 
                    425:                /* copy value received because it is not an escape
                    426:                 * sequence */
                    427:                memcpy (result + iterator, content + iterator2, 1);
                    428: 
                    429:                /* update the iterator */
                    430:                iterator++;
                    431:                iterator2++;
                    432:        }
                    433: 
                    434:        /* return results */
                    435:        return result;
                    436: }
                    437: 
                    438: /** 
                    439:  * @brief Replaces all entity references to its corresponding
                    440:  * values. This function only implements translation for default
                    441:  * recognized entities (&, <, >, ' and ").
                    442:  *
                    443:  * @param content The string content having escaped XML declarations
                    444:  * such \&gt; or \&lt; which should be
                    445:  * translated into its corresponding utf-8 symbol (for example > and
                    446:  * <).
                    447:  *
                    448:  * @param content_size A non-optional reference to an integer variable
                    449:  * which will hold the new size of the string returned. You can pass a
                    450:  * variable initialized to 0 or -1 to let the function to calculate
                    451:  * the initial string length (by using strlen).
                    452:  *
                    453:  * Because the substitution pattern applied on this operation makes
                    454:  * not necessary to allocate memory, the function return the same
                    455:  * string received, but with all values replaced. If you want to avoid
                    456:  * this behaviour, use \ref axl_strdup before calling to this
                    457:  * function.
                    458:  *
                    459:  * @return Returns the string modified or NULL if it fails.
                    460:  */
                    461: char * axl_node_content_translate_defaults (char * content, 
                    462:                                            int  * content_size)
                    463: {
                    464:        int     iterator  = 0;
                    465:        int     iterator2 = 0;
                    466:        
                    467:        axl_return_val_if_fail (content, NULL);
                    468:        axl_return_val_if_fail (content_size, NULL);
                    469: 
                    470:        /* update string length if no data was provided */
                    471:        if (*content_size == 0 || *content_size == -1)
                    472:                *content_size = strlen (content);
                    473: 
                    474:        /* iterate over all content defined */
                    475:        while (iterator < (*content_size)) {
                    476:                
                    477:                /* check for &apos; */
                    478:                if (axl_stream_cmp (content + iterator, "&apos;", 6)) {
                    479:                        content [iterator2] = '\'';
                    480:                        iterator2++;
                    481:                        
                    482:                        iterator += 6;
                    483:                        continue;
                    484:                }
                    485:                
                    486:                /* check for &quot; */
                    487:                if (axl_stream_cmp (content + iterator, "&quot;", 6)) {
                    488:                        content [iterator2] = '"';
                    489:                        iterator2++;
                    490:                        
                    491:                        iterator += 6;
                    492:                        continue;
                    493:                }
                    494: 
                    495:                /* check for &amp; */
                    496:                if (axl_stream_cmp (content + iterator, "&amp;", 5)) {
                    497:                        content [iterator2] = '&';
                    498:                        iterator2++;
                    499:                        
                    500:                        iterator += 5;
                    501:                        continue;
                    502:                }
                    503: 
                    504:                /* check for &gt; */
                    505:                if (axl_stream_cmp (content + iterator, "&gt;", 4)) {
                    506:                        content [iterator2] = '>';
                    507:                        iterator2++;
                    508:                        
                    509:                        iterator += 4;
                    510:                        continue;
                    511:                }
                    512: 
                    513:                /* check for &lt; */
                    514:                if (axl_stream_cmp (content + iterator, "&lt;", 4)) {
                    515:                        content [iterator2] = '<';
                    516:                        iterator2++;
                    517:                        
                    518:                        iterator += 4;
                    519:                        continue;
                    520:                }
                    521: 
                    522:                /* copy move the content */
                    523:                if (iterator2 != iterator)
                    524:                        content [iterator2] = content [iterator];
                    525: 
                    526:                /* update the iterator */
                    527:                iterator++;
                    528:                iterator2++;
                    529:        }
                    530: 
                    531:        /* return results, setting the new content size */
                    532:        *content_size       = iterator2;
                    533:        content [iterator2] = 0;
                    534:        return content;
                    535: }
                    536: 
                    537: 
                    538: 
                    539: /** 
                    540:  * @brief Creates a new \ref axlNode with the provided name.
                    541:  *
                    542:  * The function will perform a new local copy from the name reference
                    543:  * received. See also \ref axl_node_create_ref for an explanation
                    544:  * about how to save memory.
                    545:  *
                    546:  * @param name The name to be used for the node be created. The
                    547:  * function doesn't check if the paramater received is null.
                    548:  * 
                    549:  * @return A newly allocated \ref axlNode reference, that must be
                    550:  * deallocated by \ref axl_node_free.
                    551:  */
                    552: axlNode * axl_node_create (const char * name)
                    553: {
                    554: 
                    555:        axlNode * node;
                    556: 
                    557:        /* init the node */
                    558:        node        = axl_new (axlNode, 1);
                    559:        node->name  = axl_strdup (name);
                    560:        
                    561:        return node;
                    562: }
                    563: 
                    564: /** 
                    565:  * @brief This function allows to create a xml node from the provided
                    566:  * xml content (bootstraping XML content).
                    567:  *
                    568:  * This function is useful if it is required to create a node with a
                    569:  * particular complex content, without going into the detail of
                    570:  * creating all childs, attributes and content.
                    571:  *
                    572:  * Here is an example:
                    573:  * \code
                    574:  * axlError * error = NULL;
                    575:  * axlNode  * node  = NULL;
                    576:  * 
                    577:  * // parse document 
                    578:  * root = axl_node_parse_strings (error, 
                    579:  *                                "<child>",
                    580:  *                                "  <widget class=\"GtkLabel\" id=\"label4\">",
                    581:  *                                "    <property name=\"visible\">True</property>",
                    582:  *                                "    <property name=\"label\" translatable=\"yes\">&lt;b&gt;1. Seleccione el sistema:&lt;/b&gt;</property>",
                    583:  *                                "    <property name=\"use_underline\">False</property>",
                    584:  *                                "    <property name=\"use_markup\">True</property>",
                    585:  *                                "    <property name=\"justify\">GTK_JUSTIFY_LEFT</property>",
                    586:  *                                "    <property name=\"wrap\">False</property>",
                    587:  *                                "    <property name=\"selectable\">False</property>",
                    588:  *                                "    <property name=\"xalign\">0</property>",
                    589:  *                                "    <property name=\"yalign\">0.5</property>",
                    590:  *                                "    <property name=\"xpad\">0</property>",
                    591:  *                                "    <property name=\"ypad\">0</property>",
                    592:  *                                "    <property name=\"ellipsize\">PANGO_ELLIPSIZE_NONE</property>",
                    593:  *                                "    <property name=\"width_chars\">-1</property>",
                    594:  *                                "    <property name=\"single_line_mode\">False</property>",
                    595:  *                                "    <property name=\"angle\">0</property>",
                    596:  *                                "  </widget>",
                    597:  *                                "  <packing>",
                    598:  *                                "     <property name=\"padding\">0</property>",
                    599:  *                                "     <property name=\"expand\">False</property>",
                    600:  *                                "     <property name=\"fill\">False</property>",
                    601:  *                                "  </packing>",
                    602:  *                                "</child>",
                    603:  *                                NULL);
                    604:  * if (root == NULL) {
                    605:  *     printf ("Error: unable to parse content, error: %s\n", axl_error_get (error));
                    606:  *              axl_error_free (error);
                    607:  *     return;
                    608:  * }
                    609:  *
                    610:  * // once finished, free the node 
                    611:  * axl_node_free (root);
                    612:  * \endcode
                    613:  * 
                    614:  * @param error Optional error reference to report parsing error
                    615:  * problems that can be found.
                    616:  * 
                    617:  * The function receives a set of strings, separate by comma, ended by
                    618:  * NULL.
                    619:  * 
                    620:  * @return A newly allocated reference to the \ref axlNode or NULL if
                    621:  * it fails. In such case, the error variable is filled with the error
                    622:  * found.
                    623:  */
                    624: axlNode * axl_node_parse_strings      (axlError ** error, ...)
                    625: {
                    626:        axlDoc   * doc;
                    627:        axlNode  * root;
                    628:        va_list    args;
                    629:        char     * string     = NULL;
                    630:        char     * stream     = NULL;
                    631:        char     * stream_aux = NULL;
                    632:        
                    633:        /* check incoming data */
                    634:        axl_return_val_if_fail (error, NULL);
                    635:        
                    636:        /* open the stdargs */
                    637:        va_start (args, error);
                    638:        
                    639:        while ((string = va_arg (args, char *)) != NULL) {
                    640:                stream_aux = stream;
                    641:                stream = axl_stream_concat (stream, string);
                    642:                if (stream_aux != NULL) {
                    643:                        axl_free (stream_aux);
                    644:                        stream_aux = NULL;
                    645:                }
                    646:        }
                    647: 
                    648:        /* close the stdargs */
                    649:        va_end (args);
                    650: 
                    651:        /* check that we have received, at least, an string
                    652:         * parseable */
                    653:        if (stream == NULL)
                    654:                return NULL;
                    655: 
                    656:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "string to parse: %s", stream);
                    657: 
                    658:        /* parse the string */
                    659:        doc = axl_doc_parse (stream, -1, error);
                    660:        if (doc == NULL) {
                    661:                /* free document */
                    662:                axl_free (stream);
                    663:                return NULL;
                    664:        }
                    665: 
                    666:        /* free the stream */
                    667:        axl_free (stream);
                    668: 
                    669:        /* deattach the root node */
                    670:        root = axl_doc_get_root (doc);
                    671:        axl_node_deattach (root);
                    672: 
                    673:        /* do not free the document, rather, store it to be
                    674:         * deallocated by the node just after it is deallocated. */
                    675:        axl_node_annotate_data_full (root, "__root_document", NULL, doc, (axlDestroyFunc) axl_doc_free);
                    676: 
                    677:        /* return the node created */
                    678:        return root;
                    679: }
                    680: 
                    681: /** 
                    682:  * @brief Allows to create a complete node configuring not only the
                    683:  * node but its content, using a printf-like format.
                    684:  *
                    685:  * This handy function, like \ref axl_node_parse_strings, allows to
                    686:  * create complex xml structures providing inline content.
                    687:  *
                    688:  * Here is an example:
                    689:  * \code
                    690:  * axlNode * node = axl_node_parse (NULL, "<content attr='value' attr2='value'>This is content</content>");
                    691:  * \endcode
                    692:  *
                    693:  * The previous call will create a node called <b>content</b> with the
                    694:  * provided attributes and content, in one step.
                    695:  *
                    696:  * The node returned can be integrated into a xml document using usual
                    697:  * API, for example: \ref axl_node_set_child or \ref axl_doc_set_root.
                    698:  * 
                    699:  * @param error The optional error reference holding the returned
                    700:  * result.
                    701:  *
                    702:  * @param content The content to be used to create the node.
                    703:  * 
                    704:  * @return A reference to a newly allocated \ref axlNode or NULL if it
                    705:  * fails. The \ref axlError is filled with the error found if provided
                    706:  * by the caller.
                    707:  */
                    708: axlNode * axl_node_parse                    (axlError ** error, const char * content, ...)
                    709: {
                    710:        char    * _content;
                    711:        va_list   args;
                    712:        axlDoc  * doc;
                    713:        axlNode * root;
                    714: 
                    715:        /* open the stdargs */
                    716:        va_start (args, content);
                    717:        
                    718:        /* create the content */
                    719:        _content = axl_strdup_printfv (content, args);
                    720: 
                    721:        /* close the stdargs */
                    722:        va_end (args);
                    723: 
                    724:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parsing document:\n %s", _content);
                    725: 
                    726:        /* parse the string */
                    727:        doc = axl_doc_parse (_content, -1, error);
                    728:        if (doc == NULL) {
                    729:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "failed to parse document:\n %s", _content);
                    730: 
                    731:                /* free document */
                    732:                axl_free (_content);
                    733: 
                    734:                return NULL;
                    735:        }
                    736: 
                    737:        /* free the content */
                    738:        axl_free (_content);
                    739: 
                    740:        /* deattach the root node */
                    741:        root = axl_doc_get_root (doc);
                    742:        axl_node_deattach (root);
                    743: 
                    744:        /* do not free the document, rather, store it to be
                    745:         * deallocated by the node just after it is deallocated. */
                    746:        axl_node_annotate_data_full (root, "__root_document", NULL, doc, (axlDestroyFunc) axl_doc_free);
                    747: 
                    748:        /* return the node created */
                    749:        return root;
                    750: }
                    751: 
                    752: 
                    753: /** 
                    754:  * @brief Creates a new \ref axlNode but reusing the memory passed in
                    755:  * by the name reference.
                    756:  *
                    757:  * This function works the same way like \ref axl_node_create, but
                    758:  * previous one makes a local copy from the name provided. This means
                    759:  * that, if you have allocated the reference being passed, the
                    760:  * previous function will allocate again memory for the name
                    761:  * reference.
                    762:  *
                    763:  * Obviously, for a few xml nodes this have none or little effect but,
                    764:  * if your xml document have 100.000 nodes you save 100.000 extra
                    765:  * memory allocations and deallocations. This may improve your
                    766:  * application performace because memory
                    767:  * fragmentation/allocations/deallocations are reduced.
                    768:  *
                    769:  * Keep in mind that this function should not be used with static strings. Example:
                    770:  * \code
                    771:  *    // propery node creation 
                    772:  *    axlNode * node = axl_node_create ("test");
                    773:  *  
                    774:  *    // NOT PROPER node creation
                    775:  *    axlNode * node = axl_node_create_ref ("test");
                    776:  * \endcode
                    777:  *
                    778:  * @param name A user-space allocated memory representing the node
                    779:  * name. The function doesn't check if the parameter received is null.
                    780:  * 
                    781:  * @return A newly created \ref axlNode reference that must be
                    782:  * deallocated by \ref axl_node_free.
                    783:  */
                    784: axlNode * axl_node_create_ref         (char * name)
                    785: {
                    786:        axlNode * node;
                    787: 
                    788:        /* init the node */
                    789:        node        = axl_new (axlNode, 1);
                    790:        node->name  = name;
                    791:        
                    792:        /* return a reference to a new axlNode */
                    793:        return node;
                    794: }
                    795: 
                    796: /** 
                    797:  * @brief Allows to configure the node name, using the value provided. 
                    798:  * 
                    799:  * The function will dealloc the previous name stored, if found.
                    800:  *
                    801:  * @param node The node to be configured with a new name.
                    802:  * 
                    803:  * @param name The new name to configure on the node. Function will
                    804:  * create a local copy from the new name provided. The function won't
                    805:  * check the name parameter received to be a non-null pointer.
                    806:  */
                    807: void      axl_node_set_name                 (axlNode * node, const char * name)
                    808: {
                    809:        /* check the name to be already configured and dealloc it */
                    810:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                    811:                axl_free (node->name);
                    812:        
                    813:        /* alloc the new name */
                    814:        node->name = axl_strdup (name);
                    815:        node->conf &= ~NODE_NAME_FROM_FACTORY;
                    816:        
                    817:        return;
                    818: }
                    819: 
                    820: /** 
                    821:  * @brief Allows to configure the node name, using the value provided
                    822:  * as a reference allocated and to be owned by the node.
                    823:  * 
                    824:  * The function will dealloc the previous name stored, if found.
                    825:  *
                    826:  * @param node The node to be configured with a new name.
                    827:  * 
                    828:  * @param name The new name to configure on the node. The value
                    829:  * provided will be owned by the node. The function won't check the
                    830:  * name parameter received to be a non-null pointer.
                    831:  */
                    832: void      axl_node_set_name_ref             (axlNode * node, char * name)
                    833: {
                    834:        /* check the name to be already configured and dealloc it */
                    835:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                    836:                axl_free (node->name);
                    837: 
                    838:        /* alloc the new name */
                    839:        node->name = name;
                    840:        
                    841:        return;
                    842: }
                    843: 
                    844: /** 
                    845:  * @internal Allows to configure the xml node, flaging the string
                    846:  * received to be owned by a factory. Do not use this API from your
                    847:  * application. This is only useful for Axl Library internals.
                    848:  * 
                    849:  * @param node The xml node that is going to be configured.
                    850:  *
                    851:  * @param name The xml node name to be configured. Previous
                    852:  * configuration won't be deallocated as it is supposed that this
                    853:  * function is only used from inside axl library.
                    854:  */
                    855: void axl_node_set_name_from_factory (axlNode * node, char * name)
                    856: {
                    857:        /* set node name */
                    858:        node->name = name;
                    859: 
                    860:        /* update configuration */
                    861:        node->conf |= NODE_NAME_FROM_FACTORY;
                    862:        
                    863:        return;
                    864: }
                    865: 
                    866: axlPointer __axl_node_copy_key (axlPointer key, axlDestroyFunc key_destroy, 
                    867:                                axlPointer data, axlDestroyFunc data_destroy)
                    868: {
                    869:        /* copy the key */
                    870:        return axl_strdup (key);
                    871: }
                    872: 
                    873: axlPointer __axl_node_copy_value (axlPointer key, axlDestroyFunc key_destroy,
                    874:                                  axlPointer data, axlDestroyFunc data_destroy)
                    875: {
                    876:        /* copy data */
                    877:        return axl_strdup (data);
                    878: }
                    879: 
                    880: /** 
                    881:  * @brief Allows to perform a copy operation for the provided node.
                    882:  *
                    883:  * @param node The source node to copy.
                    884:  *
                    885:  * @param copy_attributes Signals the function to also copy node
                    886:  * attributes into the newly created node.
                    887:  *
                    888:  * @param copy_childs Signals the function to also copy childs for the
                    889:  * source node.
                    890:  * 
                    891:  * @return A newly created node copy or null if it fails. The function
                    892:  * will fail if the node reference provided is null.
                    893:  */
                    894: axlNode * axl_node_copy                     (axlNode   * node,
                    895:                                             axl_bool    copy_attributes,
                    896:                                             axl_bool    copy_childs)
                    897: {
                    898:        axlNode * result;
                    899:        axlItem * child;
                    900:        axlItem * copy;
                    901:        
                    902: 
                    903:        axl_return_val_if_fail (node, NULL);
                    904: 
                    905:        /* create the copy */
                    906:        result = axl_node_create (axl_node_get_name (node));
                    907: 
                    908:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node=<%s> (copy operation)",
                    909:                   result->name);
                    910: 
                    911:        /* check for attributes */
                    912:        if (node->attributes != NULL && copy_attributes) {
                    913:                
                    914:                /* copy attribute configuration and attributes */
                    915:                result->attr_num = node->attr_num;
                    916:                if (node->attr_num >= 11) {
                    917:                        /* copy attribute list supposing it is a
                    918:                         * hash */
                    919:                        result->attributes = (axlPointer) axl_hash_copy ((axlHash *) node->attributes, 
                    920:                                                                         /* key copy function */
                    921:                                                                         __axl_node_copy_key,
                    922:                                                                         /* value copy function */
                    923:                                                                         __axl_node_copy_value);
                    924:                } else {
                    925:                        /* copy attribute list */
                    926:                        result->attributes = (axlPointer) __axl_node_copy_attr_list ((axlNodeAttr *) node->attributes);
                    927:                }
                    928:        }
                    929: 
                    930:        /* check if child nodes must be also copied */
                    931:        if (copy_childs && (node->first != NULL)) {
                    932: 
                    933:                /* copy all content inside */
                    934:                child = node->first;
                    935:                while (child != NULL) {
                    936:                        
                    937:                        /* copy the child found */
                    938:                        copy       = axl_item_copy (child, result);
                    939:                        
                    940:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  new item created (copy operation) with parent=<%s> and type=%d",
                    941:                                   copy->parent->name,
                    942:                                   axl_item_get_type (copy));
                    943: 
                    944:                        /* set the content */
                    945:                        axl_item_set_child_ref (result, copy);
                    946: 
                    947:                        /* get the next element */
                    948:                        child = child->next;
                    949: 
                    950:                } /* end while */
                    951:        } /* end if */
                    952:        
                    953:        
                    954:        /* return the node created */
                    955:        return result;
                    956: }
                    957: 
                    958: /** 
                    959:  * @brief Allows to get the xml document (\ref axlDoc) where the
                    960:  * provided xml node is stored.
                    961:  * 
                    962:  * @param node The node that is being requested to return is xml
                    963:  * document reference.
                    964:  * 
                    965:  * @return The xml document reference or NULL if it is not already
                    966:  * set. 
                    967:  */
                    968: axlDoc  * axl_node_get_doc                  (axlNode * node)
                    969: {
                    970:        axl_return_val_if_fail (node, NULL);
                    971:        
                    972:        /* return the internal reference */
                    973:        return axl_item_get_doc (node->holder);
                    974: }
                    975: 
                    976: /** 
                    977:  * @internal
                    978:  *
                    979:  * This function is not provided to the public API because it is used
                    980:  * by the Axl internals to set the root node for a provided xml node,
                    981:  * that is usually the root document xml node.
                    982:  * 
                    983:  * @param node The node that is being configured to have, or being contained in, the provided xml document.
                    984:  *
                    985:  * @param doc The xml document that holds the node.
                    986:  */
                    987: void      axl_node_set_doc                  (axlNode * node, axlDoc * doc)
                    988: {
                    989:        axlItem * item;
                    990: 
                    991:        axl_return_if_fail (node);
                    992:        axl_return_if_fail (doc);
                    993: 
                    994:        /* get the item reference */
                    995:        item = node->holder;
                    996: 
                    997:        if (item == NULL) {
                    998: 
                    999:                /* create an empty reference */
                   1000:                item         = axl_item_factory_get (axl_doc_get_item_factory (doc)); 
                   1001:                item->type   = ITEM_NODE | ITEM_FROM_FACTORY;
                   1002:                item->data   = node;
                   1003:                node->holder = item;
                   1004:                
                   1005:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node received doesn't have a holder reference, creating ref=0x%x, node=0x%x, type=%d",
                   1006:                           item, node, item->type);
                   1007:        } /* end if */
                   1008: 
                   1009:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting doc to the item node");
                   1010: 
                   1011:        /* call to set item at the document */
                   1012:        item->doc = doc;
                   1013: 
                   1014:        return;
                   1015: }
                   1016: 
                   1017: 
                   1018: /** 
                   1019:  * @internal
                   1020:  * 
                   1021:  * Support function to install attribute information provided into the
                   1022:  * \ref axlNode provided.
                   1023:  *
                   1024:  * @return axl_true if the attribute was added, otherwise axl_false is
                   1025:  * returned.
                   1026:  */
                   1027: axl_bool      __axl_node_set_attribute      (axlFactory * factory, 
                   1028:                                             axlNode    * node, 
                   1029:                                             char       * attribute, 
                   1030:                                             char       * value, 
                   1031:                                             axl_bool     from_factory)
                   1032: {
                   1033:        axlNodeAttr * attr;
                   1034:        axlNodeAttr * next;
                   1035: 
                   1036:        /* init attribute list */
                   1037:        /* do not init attribute list twice */
                   1038:        if (node->attributes == NULL) {
                   1039:                /* configure default axl attribute list */
                   1040:                node->attr_num   = 1;
                   1041:                
                   1042:                /* create the node */
                   1043:                if (from_factory)
                   1044:                        attr = axl_factory_get (factory);
                   1045:                else
                   1046:                        attr = axl_new (axlNodeAttr, 1);
                   1047:                attr->from_factory = from_factory;
                   1048:                attr->attribute    = attribute;
                   1049:                attr->value        = value;
                   1050:                
                   1051:                /* store the node */
                   1052:                node->attributes = (axlPointer) attr;
                   1053: 
                   1054:                return axl_true;
                   1055:        }
                   1056: 
                   1057:        /* store the attribute using the general case */
                   1058:        if (node->attr_num < 10) {
                   1059: 
                   1060:                /* check if the attribute exists */
                   1061:                if (axl_node_has_attribute (node, attribute))
                   1062:                        return axl_false;
                   1063: 
                   1064:                /* create the node */
                   1065:                if (from_factory)
                   1066:                        attr = axl_factory_get (factory);
                   1067:                else
                   1068:                        attr = axl_new (axlNodeAttr, 1);
                   1069:                attr->from_factory = from_factory;
                   1070:                attr->attribute    = attribute;
                   1071:                attr->value        = value;
                   1072: 
                   1073:                /* set the next to the new item to be the current first */
                   1074:                attr->next       = (axlNodeAttr *) node->attributes;
                   1075: 
                   1076:                /* set the new first */
                   1077:                node->attributes = (axlPointer) attr;
                   1078:                
                   1079:        } else if (node->attr_num >= 10) {
                   1080: 
                   1081:                /* check if the attribute exists */
                   1082:                if (axl_node_has_attribute (node, attribute))
                   1083:                        return axl_false;
                   1084:                
                   1085:                /* check if we have to translate current attributes */
                   1086:                if (node->attr_num == 10) {
                   1087:                        /* get a reference to current attribute list */
                   1088:                        attr = (axlNodeAttr *) node->attributes;
                   1089: 
                   1090:                        /* create the hash */
                   1091:                        node->attributes = (axlPointer) axl_hash_new_full (axl_hash_string, axl_hash_equal_string, 1);
                   1092:                        
                   1093:                        while (attr != NULL) {
                   1094:                                /* add the attribute */ 
                   1095:                                axl_hash_insert_full ((axlHash *) node->attributes, 
                   1096:                                                      /* attribute name */
                   1097:                                                      attr->attribute, attr->from_factory ?  NULL : axl_free, 
                   1098:                                                      /* attribute value */
                   1099:                                                      attr->value, attr->from_factory ? NULL : axl_free);
                   1100:                                /* free current node */
                   1101:                                next = attr->next;
                   1102:                                if (! attr->from_factory)
                   1103:                                        axl_free (attr);
                   1104: 
                   1105:                                /* get the next item to store */
                   1106:                                attr = next;
                   1107:                        } /* end while */
                   1108: 
                   1109:                } /* end if */
                   1110: 
                   1111:                /* add the attribute */ 
                   1112:                axl_hash_insert_full ((axlHash *) node->attributes, 
                   1113:                                      attribute, from_factory ? NULL : axl_free, 
                   1114:                                      value, from_factory ? NULL : axl_free);                           
                   1115:                
                   1116:        } /* end if */
                   1117: 
                   1118:        /* update attribute count */
                   1119:        node->attr_num++;
                   1120: 
                   1121:        return axl_true;
                   1122: }
                   1123: 
                   1124: /** 
                   1125:  * @brief Allows to configure an xml attribute on the given node.
                   1126:  *
                   1127:  * \code
                   1128:  * <complex attr1='value'>
                   1129:  *   ..
                   1130:  * </complex>
                   1131:  * \endcode
                   1132:  *
                   1133:  * It is not allowed to store the same attribute twice inside the same
                   1134:  * node. If the function detects that a node is being set to have the
                   1135:  * same attribute name several times, the attribute will be silently
                   1136:  * not added.
                   1137:  *
                   1138:  * Values for the attribute name (<b>attribute</b>) and its associated
                   1139:  * value can be deallocated once the function finish. This function
                   1140:  * will perform a local copy.
                   1141:  * 
                   1142:  * @param node The \ref axlNode where the attribute will be installed.
                   1143:  *
                   1144:  * @param attribute The attribute name to configure. This value can't
                   1145:  * be NULL.
                   1146:  *
                   1147:  * @param value The value associated to the attribute to be
                   1148:  * configured. This value can't be NULL.
                   1149:  */
                   1150: void      axl_node_set_attribute      (axlNode    * node, 
                   1151:                                       const char * attribute, 
                   1152:                                       const char * value)
                   1153: {
                   1154:        int    additional_size = 0;
                   1155:        char * _attr;
                   1156:        char * _value;
                   1157: 
                   1158:        axl_return_if_fail (node);
                   1159:        axl_return_if_fail (attribute);
                   1160:        axl_return_if_fail (value);
                   1161: 
                   1162:        /* check for empty attribute names */
                   1163:        if (attribute[0] == 0) {
                   1164:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "skipping setting attribute with no name!");
                   1165:                return;
                   1166:        }
                   1167: 
                   1168:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting attribute: %s='%s'", attribute, value);
                   1169: 
                   1170:        /* check attribute name */
                   1171:        if (axl_node_has_invalid_chars (attribute, strlen (attribute),
                   1172:                                        &additional_size)) {
                   1173: 
                   1174:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found attribute content with escapable, non-valid content");
                   1175:                _attr = __axl_node_content_copy_and_escape (attribute, 
                   1176:                                                            strlen (attribute),
                   1177:                                                            additional_size,
                   1178:                                                            axl_false);
                   1179:        }else {
                   1180: 
                   1181:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "'%s' is a valid string..", attribute);
                   1182:                _attr = axl_strdup (attribute);
                   1183:        }
                   1184: 
                   1185:        /* check attribute value */
                   1186:        additional_size = 0;
                   1187:        if (axl_node_has_invalid_chars (value, strlen (value),
                   1188:                                        &additional_size)) {
                   1189: 
                   1190:                _value = __axl_node_content_copy_and_escape (value, 
                   1191:                                                             strlen (value),
                   1192:                                                             additional_size,
                   1193:                                                             axl_false);
                   1194:        }else {
                   1195:                
                   1196:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "'%s' is a valid string..", value);
                   1197:                _value = axl_strdup (value);
                   1198:        }
                   1199: 
                   1200:        /* insert the attribute */
                   1201:        if (! __axl_node_set_attribute (NULL, node, _attr, _value, axl_false)) {
                   1202:                axl_free (_attr);
                   1203:                axl_free (_value);
                   1204:        } /* end if */
                   1205:        
                   1206:        return;
                   1207: }
                   1208: 
                   1209: /** 
                   1210:  * @brief Allows to install a new attribute pair, based on the
                   1211:  * attribute name and the attribute value, without allocating memory
                   1212:  * for them.
                   1213:  * 
                   1214:  * This function works the same way like \ref axl_node_set_attribute
                   1215:  * but reusing memory allocated by the user space.
                   1216:  * 
                   1217:  * @param node The \ref axlNode where the attributes will be
                   1218:  * installed.
                   1219:  *
                   1220:  * @param attribute The attribute name to be installed.
                   1221:  *
                   1222:  * @param value The attribute value to be installed.
                   1223:  */
                   1224: void      axl_node_set_attribute_ref  (axlNode * node, char * attribute, char * value)
                   1225: {
                   1226: 
                   1227:        axl_return_if_fail (node);
                   1228:        axl_return_if_fail (attribute);
                   1229:        axl_return_if_fail (value);
                   1230: 
                   1231:        /* insert the attribute */
                   1232:        if (! __axl_node_set_attribute (NULL, node, attribute, value, axl_false)) {
                   1233:                axl_free (attribute);
                   1234:                axl_free (value);
                   1235:                return;
                   1236:        } /* end if */
                   1237: 
                   1238:        return;
                   1239: }
                   1240: 
                   1241: /** 
                   1242:  * @internal Function that allows configuring attributes to the
                   1243:  * selected node, notifying that they come from a factory and
                   1244:  * shouldn't be deallocated in the usual way. This function shouldn't
                   1245:  * be used by API consumers. This is only useful for Axl Library
                   1246:  * internals.
                   1247:  * 
                   1248:  * @param node The node to be configured with the attribute values.
                   1249:  *
                   1250:  * @param attribute The attribute to configure.
                   1251:  * @param value The attribute value to configure.
                   1252:  */
                   1253: void      axl_node_set_attribute_from_factory  (axlFactory * factory, 
                   1254:                                                axlNode    * node, 
                   1255:                                                char       * attribute, 
                   1256:                                                char       * value)
                   1257: {
                   1258:        /* insert the attribute */
                   1259:        __axl_node_set_attribute (factory, node, attribute, value, axl_true);
                   1260: 
                   1261:        return;
                   1262: }
                   1263: 
                   1264: /** 
                   1265:  * @brief Allows to check if a particular attribute is installed on
                   1266:  * the given node.
                   1267:  *
                   1268:  * @param node The node where the attribute will be checked to be
                   1269:  * configured.
                   1270:  *
                   1271:  * @param attribute The attribute to check.
                   1272:  * 
                   1273:  * @return A \ref axl_true if the attribute value is set, otherwise
                   1274:  * \ref axl_false is returned.
                   1275:  *
                   1276:  * See also \ref HAS_ATTR.
                   1277:  */
                   1278: axl_bool          axl_node_has_attribute      (axlNode * node, const char * attribute)
                   1279: {
                   1280:        axlNodeAttr * attr;
                   1281: 
                   1282:        axl_return_val_if_fail (node,      axl_false);
                   1283:        axl_return_val_if_fail (attribute, axl_false);
                   1284: 
                   1285:        /* check for empty hash */
                   1286:        if (node->attributes == NULL)
                   1287:                return axl_false;
                   1288: 
                   1289:        if (node->attr_num <= 10) {
                   1290:                /* linked configuration */
                   1291:                attr = (axlNodeAttr *) node->attributes;
                   1292:                while (attr != NULL) {
                   1293:                        /* check that the attribute is equal */
                   1294:                        if (axl_cmp (attr->attribute, attribute))
                   1295:                                return axl_true;
                   1296: 
                   1297:                        /* get the next attribute */
                   1298:                        attr = attr->next;
                   1299:                } /* end while */
                   1300: 
                   1301:                /* attribute not found */
                   1302:                return axl_false;
                   1303:        } /* end if */
                   1304: 
                   1305:        /* hashed configuration */
                   1306:        return axl_hash_exists ((axlHash *) node->attributes, (axlPointer) attribute);
                   1307: }
                   1308: 
1.1.1.2 ! misho    1309: axl_bool __axl_node_remove_attribute_reinsert  (axlPointer key, axlPointer data, axlPointer user_data)
        !          1310: {
        !          1311:        
        !          1312:        /* re-add attributes into the node */
        !          1313:        axl_node_set_attribute (user_data, key, data);
        !          1314: 
        !          1315:        return axl_false; /* do not stop until process all nodes */
        !          1316: }
        !          1317: 
1.1       misho    1318: /** 
                   1319:  * @brief Allows to remove the provided attribute, from the node
                   1320:  * provided.
                   1321:  * 
                   1322:  * @param node The node to be updated by removing the attribute
                   1323:  * provided.
                   1324:  *
                   1325:  * @param attribute The attribute to locate and remove.
                   1326:  */
                   1327: void      axl_node_remove_attribute         (axlNode    * node,
                   1328:                                             const char * attribute)
                   1329: {
                   1330:        axlNodeAttr * attr;
                   1331:        axlNodeAttr * previous;
1.1.1.2 ! misho    1332:        axlHash     * temp;
1.1       misho    1333: 
                   1334:        axl_return_if_fail (node);
                   1335:        axl_return_if_fail (attribute);
                   1336: 
                   1337:        /* check for empty hash */
                   1338:        if (node->attributes == NULL)
                   1339:                return;
                   1340: 
                   1341:        if (node->attr_num <= 10) {
                   1342:                /* linked configuration */
                   1343:                attr     = (axlNodeAttr *) node->attributes;
                   1344:                previous = NULL;
                   1345:                while (attr != NULL) {
                   1346:                        /* check that the attribute is equal */
                   1347:                        if (axl_cmp (attr->attribute, attribute)) {
                   1348:                                /* attribute found */
                   1349:                                if (previous == NULL)
                   1350:                                        node->attributes = (axlPointer) attr->next;
                   1351:                                else
                   1352:                                        previous->next = attr->next;
                   1353: 
                   1354:                                /* do not decrease attribute number
                   1355:                                 * since it is used to know the kind
                   1356:                                 * of store used. */
                   1357: 
                   1358:                                /* now dealloc the attribute */
                   1359:                                if (! attr->from_factory) {
                   1360:                                        axl_free (attr->attribute);
                   1361:                                        axl_free (attr->value);
                   1362:                                        axl_free (attr);
                   1363:                                } /* end if */
1.1.1.2 ! misho    1364: 
        !          1365:                                /* update attribute count */
        !          1366:                                node->attr_num--;
1.1       misho    1367:                                
                   1368:                                return;
                   1369:                        }
                   1370: 
                   1371:                        /* get the next attribute */
                   1372:                        previous = attr;
                   1373:                        attr     = attr->next;
                   1374:                } /* end while */
                   1375: 
                   1376:                /* attribute not found */
                   1377:                return;
                   1378:        } /* end if */
                   1379: 
                   1380:        /* hashed configuration */
                   1381:        axl_hash_remove ((axlHash *) node->attributes, (axlPointer) attribute);
                   1382: 
1.1.1.2 ! misho    1383:        /* update attributes stored */
        !          1384:        
        !          1385:        node->attr_num = axl_hash_items ((axlHash *) node->attributes);
        !          1386: 
        !          1387:        /* if we have fewer than the provided number, rebuild structure */
        !          1388:        if (node->attr_num == 10) {
        !          1389:                /* reconvert attribute format */
        !          1390:                temp = (axlHash *) node->attributes;
        !          1391:                node->attributes = NULL;
        !          1392:                node->attr_num   = 0;
        !          1393:                
        !          1394:                /* reinsert nodes */
        !          1395:                axl_hash_foreach (temp, __axl_node_remove_attribute_reinsert, node);
        !          1396: 
        !          1397:                /* release hash */
        !          1398:                axl_hash_free (temp);
        !          1399: 
        !          1400:                printf ("Number of items after reinserting..%d\n", node->attr_num);
        !          1401:        } /* end if */
1.1       misho    1402:        
                   1403:        return;
                   1404: }
                   1405: 
                   1406: /** 
                   1407:  * @brief Allows to get the number of attributes installed on the
                   1408:  * provided node.
                   1409:  * 
                   1410:  * @param node The node that is requested to return the number of
                   1411:  * attributes installed.
                   1412:  * 
                   1413:  * @return Number of attributes installed, or -1 if it fails.
                   1414:  */
                   1415: int       axl_node_num_attributes           (axlNode    * node)
                   1416: {
                   1417:        axl_return_val_if_fail (node, -1);
                   1418: 
                   1419:        if (node->attr_num <= 10) {
1.1.1.2 ! misho    1420:                return node->attr_num;
1.1       misho    1421:        } /* end if */
                   1422: 
                   1423:        /* hashed configuration */
                   1424:        return axl_hash_items ((axlHash *) node->attributes);
                   1425: }
                   1426: 
                   1427: /** 
                   1428:  * @brief Allows to check if the provided node has attributes
                   1429:  * installed.
                   1430:  * 
                   1431:  * @param node The node to be checked for attributes.
                   1432:  * 
                   1433:  * @return \ref axl_true if the node has attributes, otherwise \ref axl_false
                   1434:  * is returned. The function also returns \ref axl_false if a null
                   1435:  * reference for the node is provided.
                   1436:  */
                   1437: axl_bool      axl_node_has_attributes (axlNode * node)
                   1438: {
                   1439:        axl_return_val_if_fail (node, axl_false);
                   1440: 
                   1441:        /* return if the attributes reference is configured */
                   1442:        return (node->attributes != NULL);
                   1443: }
                   1444: 
                   1445: /** 
                   1446:  * @brief Allows to get current content of the provided attribute
                   1447:  * inside the given node.
                   1448:  *
                   1449:  * It is recomended to call first to \ref axl_node_has_attribute to
                   1450:  * ensure that the attribute to be reported its value already
                   1451:  * exists. See also \ref ATTR_VALUE.
                   1452:  *
                   1453:  * @param node The \ref axlNode where the attribute value associated
                   1454:  * will be returned.
                   1455:  *
                   1456:  * @param attribute The attribute that is being required for its
                   1457:  * value.
                   1458:  * 
                   1459:  * @return A string containing the attribute value or NULL if
                   1460:  * fails. Returned value must not be deallocated, it is a reference to
                   1461:  * a local copy. Use \ref axl_strdup function to get a persistent
                   1462:  * copy.
                   1463:  */
                   1464: const char    * axl_node_get_attribute_value (axlNode * node, const char * attribute)
                   1465: {
                   1466:        axlNodeAttr * attr;
                   1467: 
                   1468:        /* check values received */
                   1469:        axl_return_val_if_fail (node, NULL);
                   1470:        axl_return_val_if_fail (attribute, NULL);
                   1471: 
                   1472:        /* check for empty hash */
                   1473:        if (node->attributes == NULL)
                   1474:                return NULL;
                   1475: 
                   1476:        if (node->attr_num <= 10) {
                   1477:                /* linked configuration */
                   1478:                attr = (axlNodeAttr *) node->attributes;
                   1479:                while (attr != NULL) {
                   1480:                        /* check that the attribute is equal */
                   1481:                        if (axl_cmp (attr->attribute, attribute))
                   1482:                                return attr->value;
                   1483: 
                   1484:                        /* get the next attribute */
                   1485:                        attr = attr->next;
                   1486:                } /* end while */
                   1487:                
                   1488:                /* attribute not found */
                   1489:                return NULL;
                   1490:        } /* end if */
                   1491: 
                   1492:        /* return value stored for the provided key */
                   1493:        return axl_hash_get ((axlHash *) node->attributes, (axlPointer) attribute);
                   1494: }
                   1495: 
                   1496: /** 
                   1497:  * @brief Gets an allocated copy for the value associated to the given
                   1498:  * attribute.
                   1499:  *
                   1500:  * See \ref axl_node_get_attribute_value for more information. This
                   1501:  * function works the same way but returning an already allocated
                   1502:  * attribute value.
                   1503:  * 
                   1504:  * @param node The node where the attribute value is requested.
                   1505:  *
                   1506:  * @param attribute The attribute that is being requested.
                   1507:  * 
                   1508:  * @return A newly allocated reference that must be deallocated when
                   1509:  * no longer needed calling to \ref axl_free.
                   1510:  */
                   1511: char    * axl_node_get_attribute_value_copy (axlNode    * node, 
                   1512:                                             const char * attribute)
                   1513: {
                   1514:        const char * _value;
                   1515: 
                   1516:        /* get the attribute */
                   1517:        _value = axl_node_get_attribute_value (node, attribute);
                   1518:        axl_return_val_if_fail (_value, NULL);
                   1519:        
                   1520:        /* return a copy */
                   1521:        return axl_strdup (_value);
                   1522: }
                   1523: 
                   1524: /** 
                   1525:  * @brief Gets the attribute content for the provided attribute name,
                   1526:  * at the provided node, but translating entity references found.
                   1527:  *
                   1528:  * This function works the same way like \ref
                   1529:  * axl_node_get_attribute_value_copy, in the sense it returns a
                   1530:  * dinamically allocated copy for the attribute value requested but,
                   1531:  * at the same time, it returns the content with all entity references
                   1532:  * already translated.
                   1533:  *
                   1534:  * @param node The \ref axlNode instance where the attribute content
                   1535:  * will be returned.
                   1536:  *
                   1537:  * @param attribute The attribute name that is being requested.
                   1538:  * 
                   1539:  * @return The attribute content, already translated, for those
                   1540:  * entities found. The function returns a dinamilly allocated string
                   1541:  * so \ref axl_free must be used.
                   1542:  */
                   1543: char    * axl_node_get_attribute_value_trans (axlNode    * node, 
                   1544:                                              const char * attribute)
                   1545: {
                   1546:        char * _value;
                   1547:        int    size;
                   1548: 
                   1549:        /* get the attribute */
                   1550:        _value = (char *) axl_node_get_attribute_value (node, attribute);
                   1551:        axl_return_val_if_fail (_value, NULL);
                   1552: 
                   1553:        /* perform a local copy */
                   1554:        _value = axl_strdup (_value);
                   1555:        
                   1556:        /* return a copy */
                   1557:        size   = strlen (_value);
                   1558:        return axl_node_content_translate_defaults (_value, &size);
                   1559: }
                   1560: 
                   1561: /** 
                   1562:  * @brief Allows to get the value associated to the attribute
                   1563:  * provided, inside the node selected, removing trailing and ending
                   1564:  * white spaces (in the W3C sence: \\n, \\t, \\r, ' ').
                   1565:  *
                   1566:  * See \ref ATTR_VALUE_TRIMMED for a convenience macro.
                   1567:  * 
                   1568:  * @param node The node that is requested to return the associated 
                   1569:  * value to the attribute.
                   1570:  *
                   1571:  * @param attribute The attribute that is being requested.
                   1572:  * 
                   1573:  * @return A reference to the attribute value or NULL if it fails. The
                   1574:  * function doesn't return a copy, it returns a reference to the
                   1575:  * internal value.
                   1576:  */
                   1577: const char    * axl_node_get_attribute_value_trimmed (axlNode    * node,
                   1578:                                                      const char * attribute)
                   1579: {
                   1580:        char * _value;
                   1581: 
                   1582:        /* get the attribute */
                   1583:        _value = (char *) axl_node_get_attribute_value (node, attribute);
                   1584:        axl_return_val_if_fail (_value, NULL);
                   1585: 
                   1586:        /* trim the value */
                   1587:        axl_stream_trim (_value);
                   1588: 
                   1589:        /* return value */
                   1590:        return _value;
                   1591: }
                   1592: 
                   1593: /** 
                   1594:  * @brief Convenience function that allows to check if a particular
                   1595:  * attribute with a particular value is found at the provided node.
                   1596:  *
                   1597:  * This function will check if the attribute provided in the node is
                   1598:  * found and in such case, if the value that is contained inside the
                   1599:  * node is actually the same as the one provide to this function.
                   1600:  *
                   1601:  * You can also use hits macro associated: \ref HAS_ATTR_VALUE.
                   1602:  * 
                   1603:  * @param node The node that will be checked.
                   1604:  * @param attribute The attribute to be checked.
                   1605:  * @param value The value to checked if the attribute is found.
                   1606:  * 
                   1607:  * @return \ref axl_true if the node has the attribute with the
                   1608:  * provided value.
                   1609:  */
                   1610: axl_bool axl_node_has_attribute_value       (axlNode    * node, 
                   1611:                                             const char * attribute, 
                   1612:                                             const char * value)
                   1613: {
                   1614:        axl_return_val_if_fail (node,      axl_false);
                   1615:        axl_return_val_if_fail (attribute, axl_false);
                   1616:        axl_return_val_if_fail (value,     axl_false);
                   1617: 
                   1618:        /* return if the attribute value found is the same */
                   1619:        return axl_cmp (axl_node_get_attribute_value (node, attribute), value);
                   1620: }
                   1621: 
                   1622: /**
                   1623:  * @}
                   1624:  */
                   1625: 
                   1626: /**
                   1627:  * \defgroup axl_node_annotate Axl Node Annotate: An interface that allows associate arbitrary data to a particular node, indexed as a hash.
                   1628:  */
                   1629: 
                   1630: /** 
                   1631:  * \addtogroup axl_node_annotate
                   1632:  * @{
                   1633:  */
                   1634: 
                   1635: /** 
                   1636:  * @internal function which checks and initializes the hash used for
                   1637:  * annotated data.
                   1638:  */
                   1639: void __init_node_annotation (axlNode * node)
                   1640: {
                   1641:        if (node->annotate_data == NULL)
                   1642:                node->annotate_data =  axl_hash_new (axl_hash_string, axl_hash_equal_string);
                   1643:        return;
                   1644: }
                   1645: 
                   1646: /** 
                   1647:  * @brief Allows to store user defined data associated to the node
                   1648:  * that is not visible from an XML perspective.
                   1649:  *
                   1650:  * This function allows to store data associated to the node and to
                   1651:  * retrieve it later in an inherited fashion. This allows to store
                   1652:  * semantic/metadata information while parsing xml documents.
                   1653:  *
                   1654:  * This function stores the given key using a hash,
                   1655:  * associating the data provided on the given node. You can also check
                   1656:  * the \ref axl_node_annotate_data_full which performs the same task
                   1657:  * but allowing to provide key and data destroy functions.
                   1658:  *
                   1659:  * Once data is stored, it could be inherited by child nodes because
                   1660:  * the access to it is done using \ref axl_node_annotate_get which can
                   1661:  * configure the data lookup to into the particular node or its
                   1662:  * parents.
                   1663:  *
                   1664:  * Additionally, you can also perform annotation using native types:
                   1665:  * int, string and double. Check the following functions to do so.
                   1666:  *
                   1667:  * - \ref axl_node_annotate_int
                   1668:  * - \ref axl_node_annotate_double
                   1669:  * - \ref axl_node_annotate_string
                   1670:  *
                   1671:  * @param node The node where the annotated data will be stored.
                   1672:  *
                   1673:  * @param key The key under which the annotated data will be stored
                   1674:  * (and indexed).
                   1675:  *
                   1676:  * @param data The data to be stored associated to the key provided.
                   1677:  */
                   1678: void      axl_node_annotate_data                 (axlNode     * node, 
                   1679:                                                 const char    * key,
                   1680:                                                 axlPointer    data)
                   1681: {
                   1682:        axl_return_if_fail (node);
                   1683: 
                   1684:        /* check and init node annotation */
                   1685:        __init_node_annotation (node);
                   1686:        
                   1687:        /* insert data */
                   1688:        axl_hash_insert (node->annotate_data, (axlPointer) key, data);
                   1689: 
                   1690:        /* nothing more to do */
                   1691:        return;
                   1692: }
                   1693: 
                   1694: /** 
                   1695:  * @brief Allows to store user defined data associated to the node
                   1696:  * that is not visible from an XML perspective.
                   1697:  *
                   1698:  * See \ref axl_node_annotate_data for a long explanation. This
                   1699:  * function performs the same task as \ref axl_node_annotate_data but
                   1700:  * allowing to set a key destroy and data destroy functions. They are
                   1701:  * later used to deallocate key and data references.
                   1702:  *
                   1703:  * @param node The node where the annotated data will be stored.
                   1704:  *
                   1705:  * @param key The key under which the annotated data will be stored.
                   1706:  *
                   1707:  * @param key_destroy The destroy function to be called to deallocate
                   1708:  * the key stored.
                   1709:  *
                   1710:  * @param data The data to be stored associated to the key provided.
                   1711:  *
                   1712:  * @param data_destroy The destroy function to be called to deallocate
                   1713:  * the data provided.
                   1714:  */
                   1715: void      axl_node_annotate_data_full            (axlNode       * node,
                   1716:                                                 const char    * key,
                   1717:                                                 axlDestroyFunc  key_destroy,
                   1718:                                                 axlPointer      data,
                   1719:                                                 axlDestroyFunc  data_destroy)
                   1720: {
                   1721:        axl_return_if_fail (node);
                   1722: 
                   1723:        /* check and init node annotation */
                   1724:        __init_node_annotation (node);
                   1725: 
                   1726:        /* insert data */
                   1727:        axl_hash_insert_full (node->annotate_data, (axlPointer) key, key_destroy, data, data_destroy);
                   1728: 
                   1729:        /* nothing more to do */
                   1730:        return;
                   1731: }
                   1732: 
                   1733: /** 
                   1734:  * @brief Allows to perform a lookup for annotated data stored on the
                   1735:  * provided node.
                   1736:  * 
                   1737:  * @param node The node where the lookup will be performed.
                   1738:  *
                   1739:  * @param key The key to lookup in the \ref axlNode reference.
                   1740:  *
                   1741:  * @param lookup_in_parent Once the lookup fails in the current node,
                   1742:  * this variable allows to signal the function to also lookup the
                   1743:  * value in the parent nodes recursively. This mechanism allows to
                   1744:  * store data on parent nodes that are shared among all child nodes.
                   1745:  *
                   1746:  * @return The data associated to the key according to the lookup
                   1747:  * configuration (lookup_in_parent and lookup_in_doc).
                   1748:  */
                   1749: axlPointer axl_node_annotate_get                 (axlNode     * node,
                   1750:                                                  const char  * key,
                   1751:                                                  axl_bool      lookup_in_parent)
                   1752: {
                   1753:        axlPointer   result = NULL;
                   1754:        axlNode    * parent;
                   1755:        
                   1756:        /* check node received before nothing */
                   1757:        axl_return_val_if_fail (node, NULL);
                   1758:        axl_return_val_if_fail (key, NULL);
                   1759:        
                   1760:        /* lookup the data in the current node */
                   1761:        if (node->annotate_data != NULL) {
                   1762:                /* lookup the data */
                   1763:                result = axl_hash_get (node->annotate_data, (axlPointer) key);
                   1764: 
                   1765:                /* check result returned */
                   1766:                if (result != NULL)
                   1767:                        return result;
                   1768:        } /* end if */
                   1769: 
                   1770:        /* check if we have to lookup the data in parent nodes */
                   1771:        if (lookup_in_parent) {
                   1772:                /* get the first parent reference */
                   1773:                parent = axl_item_get_parent (node->holder);
                   1774:                
                   1775:                /* for each parent, try to lookup the data */
                   1776:                while (parent != NULL) {
                   1777:                        /* lookup the data */
                   1778:                        if (parent->annotate_data)
                   1779:                                result = axl_hash_get (parent->annotate_data, (axlPointer) key);
                   1780: 
                   1781:                        /* check result returned */
                   1782:                        if (result != NULL)
                   1783:                                return result;
                   1784: 
                   1785:                        /* get the next parent */
                   1786:                        parent = axl_item_get_parent (parent->holder);
                   1787:                }
                   1788:        }
                   1789: 
                   1790:        /* no node was found */
                   1791:        return result;
                   1792: }
                   1793: 
                   1794: /** 
                   1795:  * @internal definition to clasify node annotation.
                   1796:  */
                   1797: typedef enum {
                   1798:        /** 
                   1799:         * @internal definition to clasify int elements.
                   1800:         */
                   1801:        ANNOTATE_INT     = 0, 
                   1802:        /** 
                   1803:         * @internal definition to clasify string elements.
                   1804:         */
                   1805:        ANNOTATE_STRING  = 1, 
                   1806:        /** 
                   1807:         * @internal definition to clasify int elements.
                   1808:         */
                   1809:        ANNOTATE_DOUBLE  = 2
                   1810: } AnnotateType;
                   1811: 
                   1812: typedef struct _AnnotateNodeData {
                   1813:        /** 
                   1814:         * @internal type annotated.
                   1815:         */
                   1816:        AnnotateType type;
                   1817: 
                   1818:        /** 
                   1819:         * @internal Value annotated: int, string or double.
                   1820:         */
                   1821:        union {
                   1822:                int    int_value;
                   1823:                char * string_value;
                   1824:                double double_value;
                   1825:        } value;
                   1826: } AnnotateNodeData;
                   1827: 
                   1828: void __axl_annotate_data_free (AnnotateNodeData * data)
                   1829: {
                   1830:        if (data == NULL)
                   1831:                return;
                   1832: 
                   1833:        /* free the string */
                   1834:        if (data->type == ANNOTATE_STRING)
                   1835:                axl_free (data->value.string_value);
                   1836: 
                   1837:        /* free the data */
                   1838:        axl_free (data);
                   1839: 
                   1840:        return;
                   1841: }
                   1842: 
                   1843: /** 
                   1844:  * @brief Allows to perform an annotation to the node at runtime,
                   1845:  * storing a integer value.
                   1846:  *
                   1847:  * While using xml documents loaded into memory, each node could be
                   1848:  * processed and annotated with particular information, indexed with a
                   1849:  * key, that could be retrieved later for faster process.
                   1850:  * 
                   1851:  * This data annotation doesn't perform any modification to the xml
                   1852:  * document in any form. It is just a programming support that allows
                   1853:  * developers to avoid creating complex and independent structures to
                   1854:  * the xml document while developing XML based solutions.
                   1855:  * 
                   1856:  * While using annotation support, you can use low level functions
                   1857:  * that provide a simple way to store pointers associated to
                   1858:  * particular nodes and retrieve them using:
                   1859:  * 
                   1860:  * - \ref axl_node_annotate_data_full
                   1861:  * - \ref axl_node_annotate_data
                   1862:  * - \ref axl_node_annotate_get
                   1863:  *
                   1864:  * However, additional functions are provided to store and retreive
                   1865:  * easily integers, strings and double data annotated. See the
                   1866:  * following:
                   1867:  * 
                   1868:  *  - \ref axl_node_annotate_int
                   1869:  *  - \ref axl_node_annotate_string
                   1870:  *  - \ref axl_node_annotate_double
                   1871:  *
                   1872:  * If you use this function to store an integer data you must use \ref
                   1873:  * axl_node_annotate_get_int to retreive data stored. You can't use
                   1874:  * \ref axl_node_annotate_get.
                   1875:  * 
                   1876:  * @param node The node where the annotation will be aplied.
                   1877:  *
                   1878:  * @param key The key to index the data annotated to the node.
                   1879:  *
                   1880:  * @param int_value An integer value that will be annotated to the
                   1881:  * node received under the key provided.
                   1882:  */
                   1883: void       axl_node_annotate_int                 (axlNode    * node,
                   1884:                                                 const char * key,
                   1885:                                                 int          int_value)
                   1886: {
                   1887:        AnnotateNodeData * data;
                   1888:        
                   1889:        /* check received values */
                   1890:        axl_return_if_fail (node);
                   1891:        axl_return_if_fail (key);
                   1892: 
                   1893:        /* allocate the node */
                   1894:        data                  = axl_new (AnnotateNodeData, 1);
                   1895:        data->type            = ANNOTATE_INT;
                   1896:        data->value.int_value = int_value;
                   1897: 
                   1898:        /* annotate the value */
                   1899:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   1900:        
                   1901:        return;
                   1902: }
                   1903: 
                   1904: /** 
                   1905:  * @brief Allows to perform an annotation to the node at runtime,
                   1906:  * storing a string value.
                   1907:  *
                   1908:  * While using xml documents loaded into memory, each node could be
                   1909:  * processed and annotated with particular information, indexed with a
                   1910:  * key, that could be retrieved later for faster process.
                   1911:  * 
                   1912:  * This data annotation doesn't perform any modification to the xml
                   1913:  * document in any form. It is just a programming support that allows
                   1914:  * developers to avoid creating complex and independent structures to
                   1915:  * the xml document while developing XML based solutions.
                   1916:  * 
                   1917:  * While using annotation support, you can use low level functions
                   1918:  * that provide a simple way to store pointers associated to
                   1919:  * particular nodes and retrieve them using:
                   1920:  * 
                   1921:  * - \ref axl_node_annotate_data_full
                   1922:  * - \ref axl_node_annotate_data
                   1923:  * - \ref axl_node_annotate_get
                   1924:  *
                   1925:  * However, additional functions are provided to store and retreive
                   1926:  * easily integers, strings and double data annotated. See the
                   1927:  * following:
                   1928:  * 
                   1929:  *  - \ref axl_node_annotate_int
                   1930:  *  - \ref axl_node_annotate_string
                   1931:  *  - \ref axl_node_annotate_double
                   1932:  *
                   1933:  * If you use this function to store a string data you must use \ref
                   1934:  * axl_node_annotate_get_string to retreive data stored. You can't use \ref axl_node_annotate_get.
                   1935:  *
                   1936:  * @param node The node where the annotation will be aplied.
                   1937:  *
                   1938:  * @param key The key to index the data annotated to the node.
                   1939:  *
                   1940:  * @param string_value A string value that will be annotated to the
                   1941:  * node received under the key provided. This value will be copied and
                   1942:  * released once the node is deallocated.
                   1943:  */
                   1944: void       axl_node_annotate_string              (axlNode       * node,
                   1945:                                                 const char    * key,
                   1946:                                                 const char    * string_value)
                   1947: {
                   1948:        AnnotateNodeData * data;
                   1949:        
                   1950:        /* check received values */
                   1951:        axl_return_if_fail (node);
                   1952:        axl_return_if_fail (key);
                   1953:        axl_return_if_fail (string_value);
                   1954: 
                   1955:        /* allocate the node */
                   1956:        data                     = axl_new (AnnotateNodeData, 1);
                   1957:        data->type               = ANNOTATE_STRING;
                   1958:        data->value.string_value = axl_strdup (string_value);
                   1959: 
                   1960:        /* annotate the value */
                   1961:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   1962:        
                   1963:        return;
                   1964: }
                   1965: 
                   1966: /** 
                   1967:  * @brief Allows to perform an annotation to the node at runtime,
                   1968:  * storing a double value.
                   1969:  *
                   1970:  * While using xml documents loaded into memory, each node could be
                   1971:  * processed and annotated with particular information, indexed with a
                   1972:  * key, that could be retrieved later for faster process.
                   1973:  * 
                   1974:  * This data annotation doesn't perform any modification to the xml
                   1975:  * document in any form. It is just a programming support that allows
                   1976:  * developers to avoid creating complex and independent structures to
                   1977:  * the xml document while developing XML based solutions.
                   1978:  * 
                   1979:  * While using annotation support, you can use low level functions
                   1980:  * that provide a simple way to store pointers associated to
                   1981:  * particular nodes and retrieve them using:
                   1982:  * 
                   1983:  * - \ref axl_node_annotate_data_full
                   1984:  * - \ref axl_node_annotate_data
                   1985:  * - \ref axl_node_annotate_get
                   1986:  *
                   1987:  * However, additional functions are provided to store and retreive
                   1988:  * easily integers, strings and double data annotated. See the
                   1989:  * following:
                   1990:  * 
                   1991:  *  - \ref axl_node_annotate_int
                   1992:  *  - \ref axl_node_annotate_string
                   1993:  *  - \ref axl_node_annotate_double
                   1994:  *
                   1995:  * If you use this function to store a double data you must use \ref
                   1996:  * axl_node_annotate_get_double to retreive data stored. You can't use \ref axl_node_annotate_get.
                   1997:  * 
                   1998:  * @param node The node where the annotation will be aplied.
                   1999:  *
                   2000:  * @param key The key to index the data annotated to the node.
                   2001:  *
                   2002:  * @param double_value A string value that will be annotated to the node
                   2003:  * received under the key provided.
                   2004:  */
                   2005: void       axl_node_annotate_double              (axlNode    * node,
                   2006:                                                 const char * key,
                   2007:                                                 double       double_value)
                   2008: {
                   2009:        AnnotateNodeData * data;
                   2010:        
                   2011:        /* check received values */
                   2012:        axl_return_if_fail (node);
                   2013:        axl_return_if_fail (key);
                   2014: 
                   2015:        /* allocate the node */
                   2016:        data                     = axl_new (AnnotateNodeData, 1);
                   2017:        data->type               = ANNOTATE_DOUBLE;
                   2018:        data->value.double_value = double_value;
                   2019: 
                   2020:        /* annotate the value */
                   2021:        axl_node_annotate_data_full (node, key, NULL, data, (axlDestroyFunc) __axl_annotate_data_free);
                   2022:        
                   2023:        return;
                   2024: }
                   2025: 
                   2026: /** 
                   2027:  * @brief Allows to retrieve the annotated int value stored on the
                   2028:  * particular node, under the provided key.
                   2029:  * 
                   2030:  * @param node The node that is required to return the annotated data.
                   2031:  *
                   2032:  * @param key The key to be used to lookup for the data annotated.
                   2033:  *
                   2034:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2035:  * to signal the function to also lookup the value in the parent
                   2036:  * nodes. This mechanism allows to store data on parent nodes that are
                   2037:  * shared by child nodes.
                   2038:  *
                   2039:  * NOTE: To make this function work properly you must store double
                   2040:  * values using \ref axl_node_annotate_int. Storing values using
                   2041:  * other functions will lead to unpredictable results.
                   2042:  * 
                   2043:  * @return The integer value stored using \ref
                   2044:  * axl_node_annotate_int. If the key provided doesn't exists, the
                   2045:  * function returns 0.
                   2046:  */
                   2047: int        axl_node_annotate_get_int             (axlNode    * node,
                   2048:                                                  const char * key,
                   2049:                                                  axl_bool     lookup_in_parent)
                   2050: {
                   2051:        AnnotateNodeData * data;
                   2052:        
                   2053:        /* check received values */
                   2054:        axl_return_val_if_fail (node, 0);
                   2055:        axl_return_val_if_fail (key, 0);
                   2056: 
                   2057:        /* get the annotated data */
                   2058:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2059: 
                   2060:        /* check for null value. */
                   2061:        if (data == NULL)
                   2062:                return 0;
                   2063: 
                   2064:        if (data->type != ANNOTATE_INT) {
                   2065:                /* drop a log */
                   2066:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as integer");
                   2067:                return 0;
                   2068:        }
                   2069:        
                   2070:        /* return the integer value inside */
                   2071:        return data->value.int_value;
                   2072: }
                   2073: 
                   2074: /** 
                   2075:  * @brief Allows to retrieve the annotated string value stored on the
                   2076:  * particular node, under the provided key.
                   2077:  * 
                   2078:  * @param node The node that is required to return the annotated data.
                   2079:  *
                   2080:  * @param key The key to be used to lookup for the data annotated.
                   2081:  *
                   2082:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2083:  * to signal the function to also lookup the value in the parent
                   2084:  * nodes. This mechanism allows to store data on parent nodes that are
                   2085:  * shared by child nodes.
                   2086:  *
                   2087:  * NOTE: To make this function work properly you must store double
                   2088:  * values using \ref axl_node_annotate_string. Storing values using
                   2089:  * other functions will lead to unpredictable results.
                   2090:  * 
                   2091:  * @return The string value stored using \ref
                   2092:  * axl_node_annotate_string. If the key provided doesn't exists, the
                   2093:  * function returns NULL.
                   2094:  */
                   2095: char *     axl_node_annotate_get_string          (axlNode    * node,
                   2096:                                                  const char * key,
                   2097:                                                  axl_bool     lookup_in_parent)
                   2098: {
                   2099:        AnnotateNodeData * data;
                   2100:        
                   2101:        /* check received values */
                   2102:        axl_return_val_if_fail (node, NULL);
                   2103:        axl_return_val_if_fail (key, NULL);
                   2104: 
                   2105:        /* get the annotated data */
                   2106:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2107: 
                   2108:        /* check for null value. */
                   2109:        if (data == NULL)
                   2110:                return NULL;
                   2111: 
                   2112:        if (data->type != ANNOTATE_STRING) {
                   2113:                /* drop a log */
                   2114:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as string");
                   2115:                return NULL;
                   2116:        }
                   2117:        
                   2118:        /* return the string value inside */
                   2119:        return data->value.string_value;
                   2120: }
                   2121: 
                   2122: /** 
                   2123:  * @brief Allows to retrieve the annotated double value stored on the
                   2124:  * particular node, under the provided key.
                   2125:  * 
                   2126:  * @param node The node that is required to return the annotated data.
                   2127:  *
                   2128:  * @param key The key to be used to lookup for the data annotated.
                   2129:  *
                   2130:  * @param lookup_in_parent Once the lookup fails, this variable allows
                   2131:  * to signal the function to also lookup the value in the parent
                   2132:  * nodes. This mechanism allows to store data on parent nodes that are
                   2133:  * shared by child nodes.
                   2134:  *
                   2135:  * NOTE: To make this function work properly you must store double
                   2136:  * values using \ref axl_node_annotate_double. Storing values using
                   2137:  * other functions will lead to unpredictable results.
                   2138:  * 
                   2139:  * @return The double value stored using \ref
                   2140:  * axl_node_annotate_double. If the key provided doesn't exists, the
                   2141:  * function returns 0.0.
                   2142:  */
                   2143: double     axl_node_annotate_get_double          (axlNode    * node,
                   2144:                                                  const char * key,
                   2145:                                                  axl_bool     lookup_in_parent)
                   2146: {
                   2147:        AnnotateNodeData * data;
                   2148:        
                   2149:        /* check received values */
                   2150:        axl_return_val_if_fail (node, 0.0);
                   2151:        axl_return_val_if_fail (key, 0.0);
                   2152: 
                   2153:        /* get the annotated data */
                   2154:        data = axl_node_annotate_get (node, key, lookup_in_parent);
                   2155: 
                   2156:        /* check for null value. */
                   2157:        if (data == NULL)
                   2158:                return 0.0;
                   2159: 
                   2160:        if (data->type != ANNOTATE_DOUBLE) {
                   2161:                /* drop a log */
                   2162:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "accesing to a annotation data that isn't flaged as double");
                   2163:                return 0.0;
                   2164:        }
                   2165:        
                   2166:        /* return the double value inside */
                   2167:        return data->value.double_value;
                   2168: }
                   2169: 
                   2170: /**
                   2171:  * @}
                   2172:  */
                   2173: 
                   2174: /** 
                   2175:  * \addtogroup axl_node_module
                   2176:  * @{
                   2177:  */
                   2178: 
                   2179: /** 
                   2180:  * @brief Allows to configure the given node to be empty.
                   2181:  *
                   2182:  * A \ref axlNode is empty when it is known that the node doesn't have
                   2183:  * any content inside it as a child element. If the node has content,
                   2184:  * and the value provided to this function is \ref axl_true, the function
                   2185:  * will deallocate the content inside.
                   2186:  *
                   2187:  * You can use this function to clear all the node content (\ref
                   2188:  * ITEM_CONTENT and \ref ITEM_CDATA) found inside the node, as follows:
                   2189:  * \code
                   2190:  * // clear all content inside 
                   2191:  * axl_node_set_is_empty (node, axl_true);
                   2192:  * \endcode
                   2193:  *
                   2194:  * @param node The node to configure as empty.
                   2195:  *
                   2196:  * @param empty The value for emptyness to be used. axl_false will
                   2197:  * mean that the node is not empty.
                   2198:  */
                   2199: void      axl_node_set_is_empty (axlNode * node, axl_bool empty)
                   2200: {
                   2201:        axlItem * child;
                   2202:        axlItem * aux;
                   2203:        int       removed = 0;
                   2204:        int       count   = 0;
                   2205: 
                   2206:        axl_return_if_fail (node);
                   2207: 
                   2208:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received set to empty node=<%s> is_empty=\"%s\"",
                   2209:                   node->name, empty ? "true" : "false");
                   2210: 
                   2211:        /* do no perform any operation if axl_false is received */
                   2212:        if (! empty)
                   2213:                return;
                   2214: 
                   2215:        /* get the first child and eliminate all content */
                   2216:        child = node->first;
                   2217:        while (child != NULL) {
                   2218: 
                   2219:                /* count each item found */
                   2220:                count++;
                   2221: 
                   2222:                /* get a reference to the next */
                   2223:                aux = child->next;
                   2224: 
                   2225:                /* check item node that represents content, and
                   2226:                 * therefore, an emptyless state */
                   2227:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2228:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2229: 
                   2230:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found item content and item CDATA..");
                   2231: 
                   2232:                        /* remove the node */
                   2233:                        axl_item_remove (child, axl_true);
                   2234: 
                   2235:                        /* count each item removed */
                   2236:                        removed++;
                   2237:                        
                   2238:                } /* end if */
                   2239: 
                   2240:                /* update to the next */
                   2241:                child = aux;
                   2242:                
                   2243:        } /* end while */
                   2244: 
                   2245:        /* now check if items removed are equal to items counted */
                   2246:        if (removed == count) {
                   2247:                /* then clear node references */
                   2248:                node->first = NULL;
                   2249:                node->last  = NULL;
                   2250:        }
                   2251:        
                   2252:        return;
                   2253: }
                   2254: 
                   2255: /** 
                   2256:  * @brief Allows to get current xml node name.
                   2257:  *
                   2258:  * If it is required to check if the given \ref axlNode have a
                   2259:  * particular name you can use the macro \ref NODE_CMP_NAME.
                   2260:  *
                   2261:  * Here is an example:
                   2262:  * \code
                   2263:  * void check_name (axlNode * node) {
                   2264:  *     if (NODE_CMP_NAME (node, "data")) {
                   2265:  *         // we got a xml node called "data" 
                   2266:  *     }
                   2267:  *   // the node doesn't have that name
                   2268:  * }
                   2269:  * \endcode
                   2270:  *
                   2271:  * @param node The \ref axlNode where the name will be returned.
                   2272:  * 
                   2273:  * @return A string reference containing the name. Returned value must
                   2274:  * not deallocated. If a copy is required use \ref axl_strdup
                   2275:  * function.
                   2276:  */
                   2277: const char    * axl_node_get_name           (axlNode * node)
                   2278: {
                   2279:        axl_return_val_if_fail (node, NULL);
                   2280: 
                   2281:        return node->name;
                   2282: }
                   2283: 
                   2284: /** 
                   2285:  * @brief Allows to get the parent xml node (\ref axlNode) of the
                   2286:  * provided xml node reference.
                   2287:  *
                   2288:  * @param node The xml node that is requested to return its parent
                   2289:  * node.
                   2290:  * 
                   2291:  * @return An internal reference to the parent node, that must not be
                   2292:  * deallocated, or NULL if fails. The function will also return NULL
                   2293:  * if the node provided is the document root. The function could only
                   2294:  * fail if the provided reference is NULL.
                   2295:  */
                   2296: axlNode * axl_node_get_parent         (axlNode * node)
                   2297: {
                   2298:        axl_return_val_if_fail (node, NULL);
                   2299: 
                   2300:        /* if holder is NULL, no parent is posible */
                   2301:        if (node->holder == NULL) {
                   2302:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a node without holder (an axlItem reference), unable to get the parent reference: %s", 
                   2303:                           node->name);
                   2304:                return NULL;
                   2305:        }
                   2306: 
                   2307:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node has a holder reference, returning current parent");
                   2308:        
                   2309:        /* return the parent */
                   2310:        return node->holder->parent;
                   2311: }
                   2312: 
                   2313: /** 
                   2314:  * @brief Allows to get the node that is located, at the same level,
                   2315:  * on the next position on the child list.
                   2316:  *
                   2317:  * When a parent node holds more node childs, all of them have the
                   2318:  * same parent child, and at the same time, all of them have a brother
                   2319:  * relation. This relation makes that two nodes that are childs for a
                   2320:  * parent node, are positioned sequentially as childs for the parent.
                   2321:  *
                   2322:  * This function allows to get the next child that is stored at the
                   2323:  * next position, inside the same level, for the given child node.
                   2324:  *
                   2325:  * There are an alternative API that allows to get the next node,
                   2326:  * following to the node selected, but providing the name to match. See
                   2327:  * \ref axl_node_get_next_called.
                   2328:  *
                   2329:  * @param node The node to get the next xml node reference.
                   2330:  * 
                   2331:  * @return Returns an internal reference to the next xml node or NULL
                   2332:  * if fails. The function will also return NULL if no next xml node is
                   2333:  * found starting from the provided reference. The root node will
                   2334:  * always returns a NULL reference.
                   2335:  */
                   2336: axlNode * axl_node_get_next           (axlNode * node)
                   2337: {
                   2338:        axlItem * item;
                   2339: 
                   2340:        axl_return_val_if_fail (node, NULL);
                   2341: 
                   2342:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting next node for=<%s>", axl_node_get_name (node));
                   2343: 
                   2344:        if (node->holder == NULL) {
                   2345:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a node without item holder (maybe it wasn't inserted into a xml document)");
                   2346:                return NULL;
                   2347:        }
                   2348:        
                   2349:        /* get the next axlNode situated at the same level of the
                   2350:         * provided axlNode reference */
                   2351:        item = axl_item_get_next (node->holder);
                   2352: 
                   2353:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "%s", (item != NULL) ? "next item is defined, check if it is a node" : "next item isn't defined");
                   2354:        
                   2355:        /* while the item is not null and different from item node,
                   2356:         * get the next */
                   2357:        while (item != NULL) {
                   2358: 
                   2359:                /* get the item found */
                   2360:                if (axl_item_get_type (item) == ITEM_NODE)
                   2361:                        return item->data;
                   2362: 
                   2363:                /* get next item */
                   2364:                item = item->next;
                   2365:                
                   2366:        } /* end while */
                   2367: 
                   2368:        /* or null if no reference is defined */
                   2369:        return NULL;
                   2370: }
                   2371: 
                   2372: /** 
                   2373:  * @brief Allows to get the next node, following to the node provided,
                   2374:  * matching the given name.
                   2375:  *
                   2376:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   2377:  * use \ref axl_ns_node_get_next_called instead. See \ref
                   2378:  * axl_ns_doc_validate. </i>
                   2379:  * 
                   2380:  * @param node The node that is requested to return its next sibling
                   2381:  * node.
                   2382:  *
                   2383:  * @param name The name to match for the next node.
                   2384:  * 
                   2385:  * @return A reference to the next node or NULL if it fails. The
                   2386:  * returned reference mustn't be deallocated.
                   2387:  */
                   2388: axlNode * axl_node_get_next_called    (axlNode       * node, 
                   2389:                                       const char    * name)
                   2390: {
                   2391:        axlNode * next;
                   2392:        axl_return_val_if_fail (node, NULL);
                   2393:        axl_return_val_if_fail (name, NULL);
                   2394: 
                   2395:        /* while there is a next node */
                   2396:        next = axl_node_get_next (node);
                   2397:        while (next != NULL) {
                   2398:                /* check the node */
                   2399:                if (NODE_CMP_NAME (next, name))
                   2400:                        return next;
                   2401: 
                   2402:                /* update to the next */
                   2403:                next = axl_node_get_next (next);
                   2404:        } /* end while */
                   2405: 
                   2406:        /* no node was found */
                   2407:        return NULL;
                   2408: }
                   2409: 
                   2410: /** 
                   2411:  * @brief Allows to get the previous reference relative to the node
                   2412:  * reference provided.
                   2413:  *
                   2414:  * See \ref axl_node_get_next. Previous reference is the considered
                   2415:  * the previous node to the referenced provided that shares the same
                   2416:  * parent and it is situated in the same level.
                   2417:  * 
                   2418:  * @param node The node where the previous reference to the previous
                   2419:  * node will be returned.
                   2420:  * 
                   2421:  * @return The previous node reference or NULL if the node doesn't
                   2422:  * have previous reference or NULL if the function fails (the function
                   2423:  * only fails if the node reference provided is null).
                   2424:  */
                   2425: axlNode * axl_node_get_previous (axlNode * node)
                   2426: {
                   2427:        axlItem * item;
                   2428: 
                   2429:        axl_return_val_if_fail (node, NULL);
                   2430: 
                   2431:        /* get the previous axlNode situated at the same level of the
                   2432:         * provided axlNode reference */
                   2433:        item = axl_item_get_previous (node->holder);
                   2434: 
                   2435:        /* while the item is not null and different from item node,
                   2436:         * get the previous */
                   2437:        while ((item != NULL) && axl_item_get_type (item) !=ITEM_NODE)
                   2438:                item = axl_item_get_previous (item);
                   2439: 
                   2440:        /* return the previous reference */
                   2441:        if (item != NULL)
                   2442:                return item->data;
                   2443: 
                   2444:        /* or null if no reference is defined */
                   2445:        return NULL;
                   2446: }
                   2447: 
                   2448: /** 
                   2449:  * @brief Allows to get the previous node, preceding to the node
                   2450:  * provided, matching the given name.
                   2451:  *
                   2452:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   2453:  * use \ref axl_ns_node_get_previous_called instead. See \ref
                   2454:  * axl_ns_doc_validate. </i>
                   2455:  * 
                   2456:  * @param node The node that is requested to return its previous sibling node.
                   2457:  * @param name The name to match for the previous node.
                   2458:  * 
                   2459:  * @return A reference to the previous node or NULL if it fails. The
                   2460:  * returned reference mustn't be deallocated.
                   2461:  */ 
                   2462: axlNode *  axl_node_get_previous_called     (axlNode       * node, 
                   2463:                                             const char    * name)
                   2464: {
                   2465:        axlNode * previous;
                   2466: 
                   2467:        axl_return_val_if_fail (node, NULL);
                   2468:        axl_return_val_if_fail (name, NULL);
                   2469: 
                   2470:        /* while there is a previous node */
                   2471:        previous = axl_node_get_previous (node);
                   2472:        while (previous != NULL) {
                   2473:                /* check the node */
                   2474:                if (NODE_CMP_NAME (previous, name))
                   2475:                        return previous;
                   2476: 
                   2477:                /* update to the next */
                   2478:                previous = axl_node_get_previous (previous);
                   2479:        } /* end while */
                   2480: 
                   2481:        /* no node was found */
                   2482:        return NULL;
                   2483: 
                   2484: } 
                   2485: 
                   2486: 
                   2487: /** 
                   2488:  * @brief Allows to get the first child that holds the node.
                   2489:  *
                   2490:  * This function is considered inside the CHILDREN API, which is the
                   2491:  * set of functions that are used to handle XML documents that have
                   2492:  * node that contains more nodes or content, but not mixed.
                   2493:  *
                   2494:  * This function allows to get the first child found that is an \ref
                   2495:  * axlNode. In the case your application is handling a document that
                   2496:  * don't mix nodes and content at the same level inside another xml
                   2497:  * nodes, you'll get the expected results.
                   2498:  *
                   2499:  * But, calling to this function on a node that contains content mixed
                   2500:  * with another nodes, you will skip all items stored before the first
                   2501:  * xml node found as child. 
                   2502:  *
                   2503:  * Let's see some examples to clarify this. Provided the following xml
                   2504:  * document:
                   2505:  *
                   2506:  * \code
                   2507:  * <document>
                   2508:  *   <child>
                   2509:  *     Content
                   2510:  *   </child>
                   2511:  * </document>
                   2512:  * \endcode
                   2513:  *
                   2514:  * If you want to get a reference to the <b>child</b> node you can do
                   2515:  * the following:
                   2516:  * 
                   2517:  * \code
                   2518:  * // supposing the document is already loaded in "doc"
                   2519:  * axlNode * node = axl_doc_get_root (doc);
                   2520:  *
                   2521:  * // get the first child 
                   2522:  * node = axl_node_get_first_child (node);
                   2523:  *
                   2524:  * // now you have in "node" a reference to the child node.
                   2525:  * \endcode
                   2526:  *
                   2527:  * However, in the case the previous content mix node with content as
                   2528:  * follows:
                   2529:  *
                   2530:  * \code
                   2531:  * <document>
                   2532:  *   Some content previous to the first child.
                   2533:  *   <child>
                   2534:  *     Content
                   2535:  *   </child>
                   2536:  * </document>
                   2537:  * \endcode
                   2538:  *
                   2539:  * Using this function will make you to skip the first content, that
                   2540:  * is, <i>"Some content previous to the first child"</i>, which is found
                   2541:  * before the &lt;child> node. In the case you want to have full
                   2542:  * access to all items stored as child for a particular node, check
                   2543:  * \ref axl_item_get_first_child.
                   2544:  * 
                   2545:  * @param node The node that is requested to return its first child.
                   2546:  * 
                   2547:  * @return The first child node or NULL if it has no child node.
                   2548:  */
                   2549: axlNode * axl_node_get_first_child    (axlNode * node)
                   2550: {
                   2551:        axlItem * item;
                   2552: 
                   2553:        /* check values */
                   2554:        axl_return_val_if_fail (node, NULL);
                   2555: 
                   2556:        /* get first item child and lookup for the first child that is
                   2557:         * a node */
                   2558:        item = node->first;
                   2559:        while (item != NULL) {
                   2560:                /* check the item type */
                   2561:                if (axl_item_get_type (item) == ITEM_NODE)
                   2562:                        return item->data;
                   2563: 
                   2564:                /* get the next */
                   2565:                item = item->next;
                   2566:        }
                   2567: 
                   2568:        /* return NULL: no child axlNode was found */
                   2569:        return NULL;
                   2570: }
                   2571: 
                   2572: /** 
                   2573:  * @brief Allows to get the last child that holds the node.
                   2574:  *
                   2575:  * See also \ref axl_node_get_first_child and \ref axl_item_get_last_child.
                   2576:  * 
                   2577:  * @param node The node that is requested to return its last child.
                   2578:  * 
                   2579:  * @return The last child node or NULL if it has no child node.
                   2580:  */
                   2581: axlNode * axl_node_get_last_child     (axlNode * node)
                   2582: {
                   2583:        axlItem * item;
                   2584: 
                   2585:        /* check values */
                   2586:        axl_return_val_if_fail (node, NULL);
                   2587: 
                   2588:        /* get first item child and lookup for the first child that is
                   2589:         * a node */
                   2590:        item = node->last;
                   2591:        while (item != NULL) {
                   2592:                /* check the item type */
                   2593:                if (axl_item_get_type (item) == ITEM_NODE)
                   2594:                        return item->data;
                   2595: 
                   2596:                /* get the next */
                   2597:                item = item->previous;
                   2598:        }
                   2599: 
                   2600:        /* return NULL: no child axlNode was found */
                   2601:        return NULL;
                   2602: }
                   2603: 
                   2604: /** 
                   2605:  * @brief Allows to check if the provided \ref axlNode is empty.
                   2606:  *
                   2607:  * If a node have content, this function will return \ref
                   2608:  * axl_false. The content must not be confused with the node childs. A
                   2609:  * xml node (\ref axlNode) could be empty but have childs at the same
                   2610:  * time (\ref axl_node_have_childs).
                   2611:  *
                   2612:  * The following xml code snipet shows a xml &lt;data> node with
                   2613:  * childs that have content, but the parent node, &lt;data> do not
                   2614:  * have content, therefore is empty.
                   2615:  *
                   2616:  * \code
                   2617:  * <data>
                   2618:  *    <row>Some data</row>
                   2619:  *    <row>More content</row>
                   2620:  * </data>
                   2621:  * \endcode
                   2622:  *
                   2623:  * A node that is empty will return NULL data once called to \ref
                   2624:  * axl_node_get_content.
                   2625:  * 
                   2626:  * @param node The node to check for its empty status. 
                   2627:  * 
                   2628:  * @return \ref axl_true if the node is empty or \ref axl_false if
                   2629:  * not.
                   2630:  */
                   2631: axl_bool          axl_node_is_empty        (axlNode * node)
                   2632: {
                   2633:        axlItem * child;
                   2634:        axl_return_val_if_fail (node, axl_false);
                   2635: 
                   2636:        /* get the first child */
                   2637:        child = node->first;
                   2638:        while (child != NULL) {
                   2639:                
                   2640:                /* check item node that represents content, and
                   2641:                 * therefore, an emptyless state */
                   2642:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2643:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2644: 
                   2645:                        /* the node has content */
                   2646:                        return axl_false;
                   2647:                        
                   2648:                } /* end if */
                   2649: 
                   2650:                /* go to the next */
                   2651:                child = child->next;
                   2652: 
                   2653:        } /* end while */
                   2654: 
                   2655:        return axl_true;
                   2656: }
                   2657: 
                   2658: /** 
                   2659:  * @brief Allows to get current xml node content (\ref axlNode).
                   2660:  * 
                   2661:  * See \ref axl_node_is_empty for more details. This function allows
                   2662:  * to get current xml node content, which is the free text enclosed
                   2663:  * inside the node.
                   2664:  *
                   2665:  * Returned value is an internal reference to the content stored. So,
                   2666:  * in the case a local copy is desired, you should check \ref
                   2667:  * axl_node_get_content_copy. 
                   2668:  *
                   2669:  * Keep in mind that the content returned could have references like
                   2670:  * "&amp;" or "&quot;" which are entities references not translated
                   2671:  * into the application level values. 
                   2672:  * 
                   2673:  * This is done because while using the content, you may be interested
                   2674:  * in getting the raw content to be passed to another xml parser which
                   2675:  * is also able to process that entities.
                   2676:  *
                   2677:  * If you don't like this behaviour you can check \ref
                   2678:  * axl_node_get_content_trans which returns a copy for the xml node
                   2679:  * content with all entities references translated.
                   2680:  *
                   2681:  * Here is a summary of functions available to get the content of a
                   2682:  * node:
                   2683:  * 
                   2684:  * - \ref axl_node_get_content_copy (the same like this function but
                   2685:  * producing an independent copy)
                   2686:  *
                   2687:  * - \ref axl_node_get_content_trans (the same like this function but
                   2688:  * translating all entity references and producing an indenpendent
                   2689:  * copy).
                   2690:  *
                   2691:  * - \ref axl_node_get_content_trim (the same like this function but
                   2692:  * removing initial and trailing white spaces in the W3C sense: spaces,
                   2693:  * tabulars, carry returns and line feed values).
                   2694:  * 
                   2695:  * @param node The \ref axlNode node where the content will be retrieved.
                   2696:  *
                   2697:  * @param content_size Optional pointer to an integer variable where
                   2698:  * the content size will be reported. If the variable is not set, the
                   2699:  * function will not report the content size. If this value is
                   2700:  * configured, it will contain the content size starting from 0 up to
                   2701:  * the content size.
                   2702:  * 
                   2703:  * @return Current xml node content. You must not deallocate reference
                   2704:  * returned. If you want a permanet copy you should use \ref
                   2705:  * axl_node_get_content_copy. Keep in mind that the function will always
                   2706:  * return an string reference. In the case the node has no content, an
                   2707:  * empty string will be returned, not NULL.
                   2708:  */
                   2709: const char    * axl_node_get_content     (axlNode * node, int * content_size)
                   2710: {
                   2711:        axlNodeContent * content;
                   2712:        axlItem        * child;
                   2713: 
                   2714:        axl_return_val_if_fail (node, NULL);
                   2715: 
                   2716:        /* get the first child */
                   2717:        child = node->first;
                   2718:        while (child != NULL) {
                   2719:                
                   2720:                /* check item node that represents content, and
                   2721:                 * therefore, an emptyless state */
                   2722:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   2723:                    axl_item_get_type (child) == ITEM_CDATA) {
                   2724:                        /* cast a reference */
                   2725:                        content = child->data;
                   2726: 
                   2727:                        /* return the content */
                   2728:                        if (content_size != NULL)
                   2729:                                *content_size = content->content_size;
                   2730: 
                   2731:                        /* return a local reference */
                   2732:                        return content->content;
                   2733:                } /* end if */
                   2734: 
                   2735:                /* get the next item */
                   2736:                child = child->next;
                   2737: 
                   2738:        } /* end while */
                   2739: 
                   2740:        /* set content size to zero */
                   2741:        if (content_size != NULL)
                   2742:                *content_size = 0;
                   2743:        return "";
                   2744: }
                   2745: 
                   2746: /** 
                   2747:  * @brief Allows to set content to the given \ref axlNode instance.
                   2748:  *
                   2749:  * The xml node content is that part defined inside two balanced xml tags,
                   2750:  * using the same label. Here is an example:
                   2751:  * \code
                   2752:  * <data>
                   2753:  *   Content inside the xml node.
                   2754:  * </data>
                   2755:  * \endcode
                   2756:  *
                   2757:  * The function perform a local copy from the content received, doing
                   2758:  * all entity replacement required.
                   2759:  *
                   2760:  * The following table shows the set of characters that this function
                   2761:  * will translate into its corresponding entity:
                   2762:  *
                   2763:  * <table>
                   2764:  * <tr><td><b>Character</b></td><td>Entity name</td></tr>
                   2765:  * <tr><td>'</td><td>&amp;apos;</td></tr>
                   2766:  * <tr><td><</td><td>&amp;lt;</td></tr>
                   2767:  * <tr><td>></td><td>&amp;gt;</td></tr>
                   2768:  * <tr><td>&</td><td>&amp;amp;</td></tr>
                   2769:  * <tr><td>"</td><td>&amp;quot;</td></tr>
                   2770:  * </table>
                   2771:  *
                   2772:  * @param node The xml node, represented by an already initialized
                   2773:  * \ref axlNode, where the node content will be set.
                   2774:  *
                   2775:  * @param content The content to set to the \ref axlNode. The function
                   2776:  * will perform a local copy from it.
                   2777:  *
                   2778:  * @param content_size The content size that is being provided. If -1
                   2779:  * is used, the function will use strlen function to get current
                   2780:  * content size.
                   2781:  */
                   2782: void      axl_node_set_content        (axlNode    * node, 
                   2783:                                       const char * content, 
                   2784:                                       int          content_size)
                   2785: {
                   2786:        axlNodeContent * itemContent;
                   2787:        int              additional_size = 0;
                   2788: 
                   2789:        axl_return_if_fail (node);
                   2790:        axl_return_if_fail (content);
                   2791: 
                   2792:        /* get current content in the case a -1 is provided */
                   2793:        if (content_size == -1)
                   2794:                content_size = strlen (content);
                   2795: 
                   2796:        /* allocate the content */
                   2797:        itemContent  = axl_new (axlNodeContent, 1);
                   2798: 
                   2799:        /* check if the string received have escapable characters */
                   2800:        if (axl_node_has_invalid_chars (content, content_size, 
                   2801:                                        &additional_size)) {
                   2802:                /* copy content */
                   2803:                itemContent->content        = __axl_node_content_copy_and_escape (content, 
                   2804:                                                                                  content_size, 
                   2805:                                                                                  additional_size,
                   2806:                                                                                  axl_false);
                   2807:                /* set node content size */
                   2808:                itemContent->content_size   = content_size + additional_size;
                   2809:        }else {
                   2810:                /* set current content */
                   2811:                itemContent->content_size   = content_size;
                   2812:                itemContent->content        = axl_new (char, content_size + 1);
                   2813: 
                   2814:                /* copy content */
                   2815:                memcpy (itemContent->content, content, itemContent->content_size);
                   2816:        }
                   2817: 
                   2818:        /* add it to the current node */
                   2819:        axl_item_set_child (node, ITEM_CONTENT, itemContent);
                   2820:        
                   2821: 
                   2822:        /* job done */
                   2823:        return;
                   2824: }
                   2825: 
                   2826: /** 
                   2827:  * @internal Common implementation for axl_node_set_content_ref and
                   2828:  * axl_node_set_content_from_factory.
                   2829:  */
                   2830: void __axl_node_set_content_common_ref (axlFactory     * factory, 
                   2831:                                        axlNode        * node, 
                   2832:                                        char           * content, 
                   2833:                                        int              content_size, 
                   2834:                                        axl_bool         from_factory,
                   2835:                                        axl_bool         cdata)
                   2836: {
                   2837:        
                   2838:        axlNodeContent * itemContent;
                   2839: 
                   2840:        axl_return_if_fail (node);
                   2841:        axl_return_if_fail (content);
                   2842: 
                   2843:        /* get current content in the case a -1 is provided */
                   2844:        if (content_size == -1)
                   2845:                content_size = strlen (content);
                   2846: 
                   2847:        /* create a content checking it it comes from the
                   2848:         * factory. Because the string received could come from the
                   2849:         * factory, already allocated, do not call to allocate */
                   2850:        if (from_factory && factory)
                   2851:                itemContent = axl_factory_get (factory);
                   2852:        else 
                   2853:                itemContent = axl_new (axlNodeContent, 1);
                   2854:                
                   2855:        /* configure content size */
                   2856:        itemContent->content_size = content_size;
                   2857: 
                   2858:        /* set current content */
                   2859:        itemContent->content  = content;
                   2860: 
                   2861:        if (from_factory) {
                   2862:                if (cdata) {
                   2863:                        /* store it */
                   2864:                        axl_item_set_child (node, ITEM_CDATA | ITEM_CONTENT_FROM_FACTORY, itemContent);
                   2865:                } else {
                   2866:                        /* store it */
                   2867:                        axl_item_set_child (node, ITEM_CONTENT | ITEM_CONTENT_FROM_FACTORY, itemContent);
                   2868:                }
                   2869:        } else {
                   2870:                /* store it */
                   2871:                if (cdata) {
                   2872:                        /* store as cdata */
                   2873:                        axl_item_set_child (node, ITEM_CDATA, itemContent);
                   2874:                } else {
                   2875:                        /* store as parsed xml content */
                   2876:                        axl_item_set_child (node, ITEM_CONTENT, itemContent);
                   2877:                }
                   2878:        } /* end if */
                   2879: 
                   2880:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting xml node (name: %s) content (size: %d) %s",
                   2881:                   node->name, itemContent->content_size, itemContent->content);
                   2882: 
                   2883:        return;
                   2884: }
                   2885: 
                   2886: /** 
                   2887:  * @brief Set the content for the provided node, reusing the reference
                   2888:  * provided, without making a local copy.
                   2889:  *
                   2890:  * This function works like \ref axl_node_set_content_ref but without
                   2891:  * copy memory provided. This allows reduce memory allocations if the
                   2892:  * memory was already allocated by the user space.
                   2893:  *
                   2894:  * Because this function doesn't perform a copy, if the content
                   2895:  * received has to be escaped, the function will fail. To use this
                   2896:  * function the caller must ensure that entity references are used to
                   2897:  * especify the &, ', ", < or >.
                   2898:  *
                   2899:  * If the node have content already configured, it is deallocated,
                   2900:  * configuring new content received.
                   2901:  * 
                   2902:  * @param node The \ref axlNode where the content will be set.
                   2903:  *
                   2904:  * @param content The user space allocated content to be set to the
                   2905:  * node.
                   2906:  *
                   2907:  * @param content_size The content size.
                   2908:  */
                   2909: void      axl_node_set_content_ref    (axlNode * node, 
                   2910:                                       char * content, 
                   2911:                                       int content_size)
                   2912: {
                   2913: 
                   2914:        /* call to set content without signaling that the content
                   2915:         * wasn't allocated by a factory. */
                   2916:        __axl_node_set_content_common_ref (NULL, node, content, content_size, axl_false, axl_false);
                   2917:        
                   2918:        /* job done */
                   2919:        return; 
                   2920: }
                   2921: 
                   2922: /** 
                   2923:  * @internal Internal API used by the axl doc module to signal that
                   2924:  * the content was allocated though the string factory and shouldn't
                   2925:  * be deallocated.
                   2926:  */
                   2927: void      axl_node_set_content_from_factory (axlFactory * factory,
                   2928:                                             axlNode    * node,
                   2929:                                             char       * content,
                   2930:                                             int          content_size)
                   2931: {
                   2932:        /* call to set content without signaling that the content was
                   2933:         * allocated by a factory. */
                   2934:        __axl_node_set_content_common_ref (factory, node, content, content_size, axl_true, axl_false);
                   2935:        
                   2936:        /* job done */
                   2937:        return;
                   2938: }
                   2939: 
                   2940: /** 
                   2941:  * @brief Allows to store CDATA enclosed content on the provided node.
                   2942:  *
                   2943:  * Some characters are not allowed to be stored "as is" inside a
                   2944:  * parseable XML document. The basic set of them are: &, ', ", < or >.
                   2945:  *
                   2946:  * In order to store content containing previous characters inside an
                   2947:  * xml node, and to remain valid, functions like \ref
                   2948:  * axl_node_set_content will translate those value, into the accepted
                   2949:  * escape sequences. 
                   2950:  *
                   2951:  * As an alternative, the XML node content could be stored enclosed as
                   2952:  * a CDATA section: <![CDATA[..]]>, which allows to store unparsed
                   2953:  * characters, including those not allowed.
                   2954:  *
                   2955:  * NOTE: In the case content received includes a ]]> declaration, it
                   2956:  * is escaped to allow it. This is provided not to allow nested CDATA
                   2957:  * declarations which is not allowed by XML 1.0 standard but to allow
                   2958:  * binary content to be stored that may include a ]]> declaration.
                   2959:  * 
                   2960:  * @param node The node where the CDATA will be stored.
                   2961:  *
                   2962:  * @param content The content to store.
                   2963:  *
                   2964:  * @param content_size The content size or -1 if required Axl to
                   2965:  * figure out current sizes.
                   2966:  */
                   2967: void      axl_node_set_cdata_content  (axlNode    * node,
                   2968:                                       const char * content,
                   2969:                                       int          content_size)
                   2970: {
                   2971:        char * copy;
                   2972:        int    additional_size = 0;
                   2973: 
                   2974:        axl_return_if_fail (node);
                   2975:        axl_return_if_fail (content);
                   2976: 
                   2977:        /* reconfigure content_size if found -1 value */
                   2978:        if (content_size == -1)
                   2979:                content_size = strlen (content);
                   2980: 
                   2981:        if (axl_node_has_invalid_chars_cdata (content, content_size, &additional_size)) {
                   2982:                /* call to get escaped version */
                   2983:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "CDATA found content to scape (content size: %d): '%s'",
                   2984:                           content_size, content);
                   2985:                copy          = __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_true);
                   2986:                content_size += additional_size;
                   2987:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "CDATA content escaped        (content size: %d): '%s'",
                   2988:                           content_size, copy);
                   2989:        } else {
                   2990:                /* call to set node content */  
                   2991:                copy = axl_strdup (content);
                   2992:        } /* end if */
                   2993: 
                   2994:        /* set content */
                   2995:        __axl_node_set_content_common_ref (NULL, node, copy, content_size, axl_false, axl_true);
                   2996: 
                   2997:        return;
                   2998: }
                   2999: 
                   3000: /** 
                   3001:  * @internal Internal API used by the axl doc module to signal that
                   3002:  * the content was allocated though the string factory and shouldn't
                   3003:  * be deallocated, and the content was found inside cdata
                   3004:  * declarations.
                   3005:  */
                   3006: void      axl_node_set_cdata_content_from_factory (axlFactory * factory,
                   3007:                                                   axlNode    * node,
                   3008:                                                   char       * content,
                   3009:                                                   int          content_size)
                   3010: {
                   3011:        /* call to set content without signaling that the content was
                   3012:         * allocated by a factory. */
                   3013:        __axl_node_set_content_common_ref (factory, node, content, content_size, axl_true, axl_true);
                   3014:        
                   3015:        /* job done */
                   3016:        return; 
                   3017: }
                   3018: 
                   3019: /** 
                   3020:  * @brief Allows to configure a new comment (&lt;!-- xml comment -->) that will be
                   3021:  * stored as a child for the node provided.
                   3022:  * 
                   3023:  * The comment will be placed at the end of the current child
                   3024:  * list. So, if you want to place a xml comment before a xml node,
                   3025:  * call first to this function and then to \ref axl_node_set_child.
                   3026:  *
                   3027:  * @param node The node that will contain the comment.
                   3028:  *
                   3029:  * @param comment The comment to be stored. The function will perform
                   3030:  * a copy from it.
                   3031:  *
                   3032:  * @param comment_size The comment size or -1 to make the function to
                   3033:  * calculate it.
                   3034:  */
                   3035: void      axl_node_set_comment        (axlNode * node,
                   3036:                                       char * comment,
                   3037:                                       int    comment_size)
                   3038: {
                   3039:        axlNodeContent * content;
                   3040: 
                   3041:        axl_return_if_fail (node);
                   3042:        axl_return_if_fail (comment);
                   3043: 
                   3044:        /* check current coment size */
                   3045:        if (comment_size == -1)
                   3046:                comment_size = strlen (comment);
                   3047: 
                   3048:        /* create the comment */
                   3049:        content               = axl_new (axlNodeContent, 1);
                   3050:        content->content      = axl_new (char, comment_size + 1);
                   3051:        content->content_size = comment_size;
                   3052: 
                   3053:        /* copy the content */
                   3054:        memcpy (content->content, comment, comment_size);
                   3055: 
                   3056:        /* now store it on the node */
                   3057:        axl_item_set_child (node, ITEM_COMMENT, content);
                   3058: 
                   3059:        return;
                   3060: }
                   3061: 
                   3062: 
                   3063: /** 
                   3064:  * @brief Allows to get a copy for the content stored inside the given
                   3065:  * \ref axlNode reference. 
                   3066:  *
                   3067:  * This function works the same way than \ref axl_node_get_content but
                   3068:  * returning a copy from the internal content, that the caller is
                   3069:  * responsible of deallocating it.
                   3070:  * 
                   3071:  * @param node The \ref axlNode where the content is being required.
                   3072:  *
                   3073:  * @param content_size An optional reference to an integer variable
                   3074:  * where the content size will be returned. The function will return
                   3075:  * the content size (if the variable is defined) ranging from 0 up to
                   3076:  * the content size.
                   3077:  * 
                   3078:  * @return A newly allocated string representing the node content. 
                   3079:  */
                   3080: char    * axl_node_get_content_copy (axlNode * node, int * content_size)
                   3081: {
                   3082:        int          _content_size;
                   3083:        char       * result;
                   3084:        const char * content;
                   3085: 
                   3086:        /* get the content and check if it is defined */
                   3087:        if (content_size)
                   3088:                content = axl_node_get_content (node, content_size);
                   3089:        else
                   3090:                content = axl_node_get_content (node, &_content_size);
                   3091: 
                   3092:        /* check result */
                   3093:        if (content == NULL || strlen (content) == 0) {
                   3094:                return axl_strdup ("");
                   3095:        }
                   3096: 
                   3097:        /* allocate enough memory for the result */
                   3098:        if (content_size) {
                   3099:                result = axl_new (char, (*content_size) + 1);
                   3100:                memcpy (result, content, *content_size);
                   3101:        }else {
                   3102:                result = axl_new (char, _content_size + 1);
                   3103:                memcpy (result, content, _content_size);
                   3104:        }
                   3105:        
                   3106:        /* return a newly allocated reference to the content */
                   3107:        return result;
                   3108: }
                   3109: 
                   3110: /** 
                   3111:  * @brief Allows to get the content inside the provided node, trimming
                   3112:  * the head and trailing white spaces found.
                   3113:  *
                   3114:  * Note that calling to this function will modify the node content,
                   3115:  * removing beginig and ending "white spaces" found. Once the function
                   3116:  * is called, the node content will be returned by \ref
                   3117:  * axl_node_get_content already trimmed.
                   3118:  *
                   3119:  * @param node The node where the content will be trimmed and
                   3120:  * returned.
                   3121:  *
                   3122:  * @param content_size The node content size reference where the
                   3123:  * content size will be reported.
                   3124:  * 
                   3125:  * @return The reference returned is an internal copy that must not be
                   3126:  * deallocated. The function always return content. If the node has no
                   3127:  * content, the function will return an empty string (but never a NULL
                   3128:  * value).
                   3129:  */
                   3130: char    * axl_node_get_content_trim   (axlNode * node,
                   3131:                                       int * content_size)
                   3132: {
                   3133:        int    trimmed;
                   3134: 
                   3135:        axlNodeContent * content;
                   3136:        axlItem        * child;
                   3137: 
                   3138:        axl_return_val_if_fail (node, NULL);
                   3139: 
                   3140:        /* get the first child */
                   3141:        child = node->first;
                   3142:        while (child != NULL) {
                   3143:                
                   3144:                /* check item node that represents content, and
                   3145:                 * therefore, an emptyless state */
                   3146:                if (axl_item_get_type (child) == ITEM_CONTENT || 
                   3147:                    axl_item_get_type (child) == ITEM_CDATA) {
                   3148:                        /* cast a reference */
                   3149:                        content = child->data;
                   3150: 
                   3151:                        /* trim the content */
                   3152:                        axl_stream_trim_with_size (content->content, &trimmed);
                   3153: 
                   3154:                        /* updates current internal content size */
                   3155:                        content->content_size -= trimmed;
                   3156: 
                   3157:                        /* return the content */
                   3158:                        if (content_size != NULL)
                   3159:                                *content_size = content->content_size;
                   3160: 
                   3161:                        /* return a local reference */
                   3162:                        return content->content;
                   3163:                } /* end if */
                   3164:                
                   3165:                /* get the next item */
                   3166:                child = child->next;
                   3167: 
                   3168:        } /* end while */
                   3169: 
                   3170:        /* set content size to zero */
                   3171:        if (content_size != NULL)
                   3172:                *content_size = 0;
                   3173:        return "";
                   3174: }
                   3175: 
                   3176: void axl_node_get_content_trans_count (axlItem * item, int * count, int *total_size)
                   3177: {
                   3178:        axlNodeContent * content;
                   3179: 
                   3180:        /* reset counters received */
                   3181:        (*count)      = 0;
                   3182:        (*total_size) = 0;
                   3183:        while (item != NULL) {
                   3184: 
                   3185:                /* check item time stored and increase counting */
                   3186:                if (axl_item_get_type (item) == ITEM_CONTENT || 
                   3187:                    axl_item_get_type (item) == ITEM_CDATA) {
                   3188:                        /* found item */
                   3189:                        (*count)++;
                   3190: 
                   3191:                        /* update totals */
                   3192:                        content     = item->data;
                   3193:                        (*total_size) += content->content_size;
                   3194:                }
                   3195:                
                   3196:                /* next item */
                   3197:                item = item->next;
                   3198:        } /* end while */
                   3199:        
                   3200:        return;
                   3201: }
                   3202: 
                   3203: 
                   3204: void axl_node_get_content_trans_copy (axlItem * item, char * result)
                   3205: {
                   3206:        axlNodeContent * content;
                   3207:        int              desp;
                   3208: 
                   3209:        /* reset counters received */
                   3210:        desp = 0;
                   3211:        while (item != NULL) {
                   3212: 
                   3213:                /* check item time stored and increase counting */
                   3214:                if (axl_item_get_type (item) == ITEM_CONTENT || 
                   3215:                    axl_item_get_type (item) == ITEM_CDATA) {
                   3216:                        /* update totals */
                   3217:                        content     = item->data;
                   3218:                        
                   3219:                        /* copy content */
                   3220:                        memcpy (result + desp, content->content, content->content_size);
                   3221: 
                   3222:                        /* update iterator */
                   3223:                        desp += content->content_size;
                   3224:                }
                   3225:                
                   3226:                /* next item */
                   3227:                item = item->next;
                   3228:        } /* end while */
                   3229:        
                   3230:        return;
                   3231: }
                   3232: 
                   3233: /** 
                   3234:  * @brief Allows to the get node content, performing a memory
                   3235:  * allocation for the returned result, translating default entities
                   3236:  * values with its replacement text.
                   3237:  * 
                   3238:  * @param node The XML node where the content is being requested to be
                   3239:  * translated.
                   3240:  *
                   3241:  * @param content_size An optional reference to an integer variable to
                   3242:  * return the node content size.
                   3243:  * 
                   3244:  * @return A newly allocated string, representing the node content,
                   3245:  * with all entities references already translated into the
                   3246:  * replacement text.
                   3247:  */
                   3248: char    * axl_node_get_content_trans (axlNode * node, int * content_size)
                   3249: {
                   3250:        char    * result;
                   3251:        int       _content_size = 0;
                   3252:        int       count;
                   3253:        int       total_size;
                   3254: 
                   3255:        /* check received reference */
                   3256:        axl_return_val_if_fail (node, NULL);
                   3257: 
                   3258:        /* check if the node has one item content inside the node or
                   3259:         * several CDATA or content items */
                   3260:        axl_node_get_content_trans_count (node->first, &count, &total_size);
                   3261: 
                   3262:        /* accoring to the number of items found */
                   3263:        switch (count) {
                   3264:        case 0:
                   3265:                /* report content size */
                   3266:                if (content_size)
                   3267:                        *content_size = 0;
                   3268:                /* nothing found return */
                   3269:                return NULL;
                   3270:        case 1:
                   3271:                /* get a copy for the node content, getting the node
                   3272:                 * content size. If the user don't provide a
                   3273:                 * reference, use a local one. */
                   3274:                if (content_size)
                   3275:                        result = axl_node_get_content_copy (node, content_size);
                   3276:                else
                   3277:                        result = axl_node_get_content_copy (node, &_content_size);
                   3278:                break;
                   3279:        default:
                   3280:                /* if reached this place, only positive values from 2
                   3281:                 * up to N are found */
                   3282:                result = axl_new (char, total_size + 1);
                   3283:                if (content_size)
                   3284:                        *content_size = total_size;
                   3285:                else
                   3286:                        _content_size = total_size;
                   3287:                
                   3288:                /* now copy all content found */
                   3289:                axl_node_get_content_trans_copy (node->first, result);
                   3290:        }
                   3291:        
                   3292: 
                   3293:        /* check result returned */
                   3294:         if (result == NULL || strlen (result) == 0) {
                   3295:                /* do not perform a copy here, it is already done by
                   3296:                 * get_content_copy, even in error */
                   3297:                 return result;
                   3298:        }
                   3299: 
                   3300:        /* translate all references that performs the entities to the
                   3301:         * replacement text. */
                   3302:        if (content_size)
                   3303:                return axl_node_content_translate_defaults (result, content_size);
                   3304:        return axl_node_content_translate_defaults (result, &_content_size);
                   3305: }
                   3306: 
                   3307: 
                   3308: /** 
                   3309:  * @brief Allows to configure a child node to the given parent.
                   3310:  *
                   3311:  * This is a fundamental function while building xml document inside
                   3312:  * memory. The way the xml nodes are linked to conform the xml
                   3313:  * document structure relay on this function. 
                   3314:  * 
                   3315:  * The idea is that every call to this function makes the <b>child
                   3316:  * </b> xml node to be placed at the end of the current item child
                   3317:  * set, that represents current child list for the provided
                   3318:  * <b>parent</b>.
                   3319:  *
                   3320:  * One important question while using this function is that you must
                   3321:  * not reuse the same xml node reference, adding it several time to
                   3322:  * the same parent (or different parents). You must create a new xml
                   3323:  * node reference (axl_node_create) for every call you do to this
                   3324:  * function.
                   3325:  * 
                   3326:  * So, to build the following structure:
                   3327:  * \code
                   3328:  * <document>
                   3329:  *   <child1 />
                   3330:  *   <child2 />
                   3331:  * </document>
                   3332:  * \endcode
                   3333:  * 
                   3334:  * You must perform the following operations:
                   3335:  * \code
                   3336:  * axlNode * parent;
                   3337:  * axlNode * child;
                   3338:  * 
                   3339:  * // create the parent node 
                   3340:  * parent = axl_node_create ("document");
                   3341:  *
                   3342:  * // create the first child 
                   3343:  * child = axl_node_create ("child1");
                   3344:  *
                   3345:  * // set it to the parent 
                   3346:  * axl_node_set_child (parent, child);
                   3347:  *
                   3348:  * // create the second child 
                   3349:  * child = axl_node_create ("child2");
                   3350:  *
                   3351:  * // set it to the parent 
                   3352:  * axl_node_set_child (parent, child);
                   3353:  *
                   3354:  * \endcode
                   3355:  *
                   3356:  * See also \ref axl_node_set_child_after which could help you adding
                   3357:  * new nodes not using a parent node as a reference but a brother
                   3358:  * node.
                   3359:  *
                   3360:  * @param parent The parent node.
                   3361:  *
                   3362:  * @param child The child node. The child node must be a deep
                   3363:  * copy. Passing several references, pointing to the same value, will
                   3364:  * cause to seg fault the program at the time the parent child is
                   3365:  * deallocated. 
                   3366:  */
                   3367: void      axl_node_set_child (axlNode * parent, axlNode * child)
                   3368: {
                   3369:        axl_return_if_fail (parent);
                   3370:        axl_return_if_fail (child);
                   3371: 
                   3372:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received parent=0x%x and child=0x%x",  parent, child);
                   3373: 
                   3374:        /* set a xml node child */
                   3375:        axl_item_set_child (parent, ITEM_NODE, child);
                   3376: 
                   3377:         return;
                   3378: }
                   3379: 
                   3380: /** 
                   3381:  * @brief Sets a new child after the node provided, using it as a
                   3382:  * reference.
                   3383:  *
                   3384:  * This function is useful to allow configuring new childs placed
                   3385:  * after some particular node. The child configured will be placed
                   3386:  * after the reference and child of the reference's parent node.
                   3387:  * 
                   3388:  * @param reference The xml node acting as a reference.
                   3389:  * @param child The new xml node child to configure.
                   3390:  */
                   3391: void      axl_node_set_child_after    (axlNode * reference,
                   3392:                                       axlNode * child)
                   3393: {
                   3394:        /* call to the item implementation */
                   3395:        axl_item_set_after (reference->holder, ITEM_NODE, child);
                   3396: 
                   3397:        return;
                   3398: }
                   3399: 
                   3400: /** 
                   3401:  * @brief Allows to replace a selected node with a new reference
                   3402:  * inside its context (updating all references: next, previous and
                   3403:  * parent).
                   3404:  *
                   3405:  * The \ref axlNode replaced will be unreference according to dealloc
                   3406:  * value. 
                   3407:  * 
                   3408:  * @param node The node to be replaced by <b>new_node</b> reference.
                   3409:  *
                   3410:  * @param new_node The node that will replace <b>node</b> reference.
                   3411:  *
                   3412:  * @param dealloc Signal if <b>node</b> must be deallocated after the
                   3413:  * replace operation.
                   3414:  */
                   3415: void      axl_node_replace             (axlNode   * node, 
                   3416:                                        axlNode   * new_node,
                   3417:                                        axl_bool    dealloc)
                   3418: {
                   3419:        axlItem * p_item;
                   3420: 
                   3421:        axl_return_if_fail (node);
                   3422:        axl_return_if_fail (new_node);
                   3423: 
                   3424:        if (axl_item_get_parent (node->holder) == NULL) {
                   3425:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "replacing the root node=<%s> with <%s>..", 
                   3426:                           axl_node_get_name (node), axl_node_get_name (new_node));
                   3427:                /* seems to be a root document */
                   3428:                if (axl_item_get_doc (node->holder) != NULL) {
                   3429:                        axl_doc_set_root (axl_item_get_doc (node->holder), new_node);
                   3430:                }
                   3431:        } else {
                   3432: 
                   3433:                /* check for holder reference */
                   3434:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "replacing a non-root node=<%s> with <%s>..",
                   3435:                           axl_node_get_name (node), axl_node_get_name (new_node));
                   3436:                if (node->holder != NULL) {
                   3437: 
                   3438:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "axl item holder is defined for node=<%s>",
                   3439:                                   axl_node_get_name (node));
                   3440:                        /* get a reference to the holder item */
                   3441:                        p_item       = node->holder;
                   3442: 
                   3443:                        /* configure the new node */
                   3444:                        p_item->data = new_node;
                   3445: 
                   3446:                        /* nullify the holder reference, and configure
                   3447:                         * the holder reference in the node */
                   3448:                        node->holder     = NULL;
                   3449:                        new_node->holder = p_item;
                   3450:                        
                   3451:                } /* end if */
                   3452:        }
                   3453: 
                   3454:        /* dealloc node if configured so */
                   3455:        if (dealloc) {
                   3456:                /* free the node */
                   3457:                axl_node_free (node);
                   3458:        }
                   3459:        
                   3460:        return;
                   3461: }
                   3462: 
                   3463: /** 
                   3464:  * @brief Allows to remove the selected reference from the document
                   3465:  * containing it.
                   3466:  *
                   3467:  * The function remove the selected reference from the document. If
                   3468:  * the node asked to be removed is the root one, the node won't be
                   3469:  * removed because the \ref axl_doc_set_root doesn't accept to remove
                   3470:  * the root node.  
                   3471:  *
                   3472:  * All childs hold by the node removed from the document will also be
                   3473:  * removed if dealloc is selected.
                   3474:  * 
                   3475:  * @param node The node to remove.
                   3476:  *
                   3477:  * @param dealloc \ref axl_true to also dealloc the memory used by the
                   3478:  * node. Setting this parameter to \ref axl_false only unlinks the
                   3479:  * node from the document making possible to reuse the node in another
                   3480:  * part of the document or to move the node to a different document.
                   3481:  */
                   3482: void      axl_node_remove             (axlNode  * node,
                   3483:                                       axl_bool   dealloc)
                   3484: {
                   3485:        axlItem * item;
                   3486:        axl_return_if_fail (node);
                   3487: 
                   3488:        /* get a reference to the item element */
                   3489:        item = node->holder;
                   3490: 
                   3491:        /* check if the node is the root node of its document */
                   3492:        if (item != NULL && item->doc != NULL) {
                   3493:                if (axl_doc_get_root (item->doc) == node) {
                   3494:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attempting to dettach the root node from the document, nullify");
                   3495:                        axl_doc_set_root (item->doc, NULL);
                   3496:                } /* end if */
                   3497:        } /* end if */
                   3498:        
                   3499:        if (axl_item_get_parent (item) != NULL) {
                   3500: 
                   3501:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "doing reference relocation (remove operation) for=<%s>",
                   3502:                           node->name);
                   3503:                
                   3504:                /* make previous node to point to the new node */
                   3505:                if (item->previous != NULL) {
                   3506:                        item->previous->next = item->next;
                   3507:                }
                   3508:                
                   3509:                /* make next node to point to the new node */
                   3510:                if (item->next != NULL) {
                   3511:                        item->next->previous = item->previous;
                   3512:                }
                   3513: 
                   3514:                /* now, update the parent reference */
                   3515:                if (item->previous == NULL) {
                   3516:                        /* seems the node is the first child of the parent,
                   3517:                         * update the reference */
                   3518:                        item->parent->first = item->next;
                   3519:                }
                   3520:                
                   3521:                if (item->next == NULL) {
                   3522:                        /* seems the node is the last child of the parent,
                   3523:                         * update the reference */
                   3524:                        item->parent->last = item->previous;
                   3525:                }
                   3526: 
                   3527:                if (item != NULL) {
                   3528:                        /* disconnect the item */
                   3529:                        item->previous = NULL;
                   3530:                        item->next     = NULL;
                   3531:                } /* end if */
                   3532: 
                   3533:        } /* end if */
                   3534: 
                   3535:        /* dealloc node if configured so */
                   3536:        if (dealloc) {
                   3537:                /* free the node */
                   3538:                axl_node_free (node);
                   3539:        }
                   3540:        
                   3541:        return;
                   3542: }
                   3543: 
                   3544: /** 
                   3545:  * @brief Supposing the node is attached to a xml document (\ref
                   3546:  * axlDoc), this function allows to deattach the node from the
                   3547:  * document that is holding it.
                   3548:  * 
                   3549:  * This function is useful while requiring to reallocate nodes from
                   3550:  * parent to parent, making the parent node that is holding it to
                   3551:  * cancel its references to the node, decreasing all internal counts
                   3552:  * to the node, etc.
                   3553:  *
                   3554:  * If the node isn't attached to any document, the function does
                   3555:  * nothing.
                   3556:  * 
                   3557:  * @param node The node to deattach.
                   3558:  */
                   3559: void axl_node_deattach (axlNode * node)
                   3560: {
                   3561:        axl_return_if_fail (node);
                   3562: 
                   3563:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "deattaching node..");
                   3564: 
                   3565:        /* call to remove */
                   3566:        axl_node_remove (node, axl_false);
                   3567: 
                   3568:        return;
                   3569: }
                   3570: 
                   3571: /** 
                   3572:  * @brief Allows to configure that the given node have child nodes.
                   3573:  *
                   3574:  * <b>DEPRECATED:</b> The function doesn't perform any operation. See
                   3575:  * \ref axl_node_have_childs.
                   3576:  * 
                   3577:  * @param node The node to configure.
                   3578:  *
                   3579:  * @param childs The child configuration, \ref axl_true to notify that
                   3580:  * the node have childs, otherwise, \ref axl_false is returned.
                   3581:  */
                   3582: void      axl_node_set_have_childs (axlNode * node, axl_bool childs)
                   3583: {
                   3584:        /* do nothing */
                   3585:        return;
                   3586: }
                   3587: 
                   3588: /** 
                   3589:  * @brief Allows to get current childs configuration from the given
                   3590:  * xml node (\ref axlNode).
                   3591:  *
                   3592:  * An xml node (represented by an \ref axlNode) is considered to have
                   3593:  * childs only if it has more xml child nodes. The content is not
                   3594:  * considered be a child. See \ref axl_node_is_empty for more
                   3595:  * information.
                   3596:  * 
                   3597:  * @param node The \ref axlNode reference.
                   3598:  * 
                   3599:  * @return An \ref axl_true if the \ref axlNode have childs or \ref
                   3600:  * axl_false if not.
                   3601:  */
                   3602: axl_bool          axl_node_have_childs        (axlNode * node)
                   3603: {
                   3604:        axlItem * item;
                   3605: 
                   3606:        axl_return_val_if_fail (node, axl_false);
                   3607: 
                   3608:        item = node->first;
                   3609:        while (item != NULL) {
                   3610:                /* check item type */
                   3611:                if (axl_item_get_type (item) == ITEM_NODE)
                   3612:                        return axl_true;
                   3613: 
                   3614:                /* go to the next */
                   3615:                item = item->next;
                   3616: 
                   3617:        } /* end while */
                   3618: 
                   3619:        /* return axl_false because no item was found with ITEM_NODE
                   3620:         * type */
                   3621:        return axl_false;
                   3622: }
                   3623: 
                   3624: /** 
                   3625:  * @internal Function that allows to check if the provided node have
                   3626:  * childs, including in the list, nodes, comments, 
                   3627:  * 
                   3628:  * @param node 
                   3629:  * 
                   3630:  * @return 
                   3631:  */
                   3632: axl_bool          axl_node_have_childs_aux        (axlNode * node)
                   3633: {
                   3634:        axlItem * item;
                   3635: 
                   3636:        axl_return_val_if_fail (node, axl_false);
                   3637: 
                   3638:        item = node->first;
                   3639:        while (item != NULL) {
                   3640:                /* check item type */
                   3641:                if (axl_item_get_type (item) == ITEM_NODE || 
                   3642:                    axl_item_get_type (item) == ITEM_PI || 
                   3643:                    axl_item_get_type (item) == ITEM_COMMENT)
                   3644:                        return axl_true;
                   3645: 
                   3646:                /* go to the next */
                   3647:                item = item->next;
                   3648: 
                   3649:        } /* end while */
                   3650: 
                   3651:        /* return axl_false because no item was found with ITEM_NODE
                   3652:         * type */
                   3653:        return axl_false;
                   3654: }
                   3655: 
                   3656: /** 
                   3657:  * @brief Allows to get a particular child node from the given node
                   3658:  * (\ref axlNode).
                   3659:  *
                   3660:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   3661:  * use \ref axl_ns_node_get_child_called instead. See \ref
                   3662:  * axl_ns_doc_validate. </i>
                   3663:  * 
                   3664:  * @param parent The parent node where the child will be looked up.
                   3665:  *
                   3666:  * @param name The name for the child to search.
                   3667:  * 
                   3668:  * @return A refernce to a \ref axlNode or NULL if no child exists
                   3669:  * called by the name provided, inside the node provided.
                   3670:  */
                   3671: axlNode * axl_node_get_child_called   (axlNode * parent, const char * name)
                   3672: {
                   3673:        axlNode * node;
                   3674:        axlItem * item;
                   3675:        
                   3676:        axl_return_val_if_fail (parent, NULL);
                   3677:        axl_return_val_if_fail (name, NULL);
                   3678: 
                   3679:        /* if the child list is not defined, assume there is no node
                   3680:         * called the name requested */
                   3681:        if (parent->first == NULL)
                   3682:                return NULL;
                   3683:        
                   3684:        /* if no childs, no result */
                   3685:        item = parent->first;
                   3686:        while (item != NULL) {
                   3687:                /* check item type */
                   3688:                if (axl_item_get_type (item) == ITEM_NODE) {
                   3689:                        /* get a reference to the node */
                   3690:                        node = item->data;
                   3691: 
                   3692:                        /* compare for find the child */ 
                   3693:                        if (NODE_CMP_NAME (node, name))
                   3694:                                return node;
                   3695:                        
                   3696:                } /* end if */
                   3697: 
                   3698:                /* next child */
                   3699:                item = axl_item_get_next (item);
                   3700:        }
                   3701: 
                   3702:        /* no child was found */
                   3703:        return NULL;
                   3704: }
                   3705: 
                   3706: /** 
                   3707:  * @brief Allows to find the first child called <b>name</b>, inside
                   3708:  * all childs (including its descendants) held by the parent provided.
                   3709:  *
                   3710:  * This function is similar to \ref axl_node_get_child_called but
                   3711:  * though it will also look for a child node called as provided not
                   3712:  * only in direct childs but also on its all descendants.
                   3713:  *
                   3714:  * If you are looking for a function to search for a particular child
                   3715:  * node inside direct childs stored for the provided parent, then you
                   3716:  * must use \ref axl_node_get_child_called.
                   3717:  *
                   3718:  * There is also a convenience function that allows to perform a
                   3719:  * lookup using as a reference a document (using the root node from
                   3720:  * it): \ref axl_doc_find_called.
                   3721:  *
                   3722:  * <i><b>NOTE:</b> This function isn't XML Namespace aware. You must
                   3723:  * use \ref axl_ns_node_find_called instead. See \ref
                   3724:  * axl_ns_doc_validate. </i>
                   3725:  *
                   3726:  * @param parent The parent where the lookup will be produced.
                   3727:  *
                   3728:  * @param name The name of the child to be looked up.
                   3729:  * 
                   3730:  * @return A reference to the node found (first instaned matching the
                   3731:  * name) or NULL if it fails to find a child.
                   3732:  */
                   3733: axlNode * axl_node_find_called    (axlNode * parent, const char * name)
                   3734: {
                   3735:        axlNode * node;
                   3736:        axlNode * child;
                   3737: 
                   3738:        /* for the first child found */
                   3739:        node = axl_node_get_first_child (parent);
                   3740:        while (node != NULL) {
                   3741:                /* check and return the node found */
                   3742:                if (NODE_CMP_NAME (node, name))
                   3743:                        return node;
                   3744:                
                   3745:                /* get next */
                   3746:                node = axl_node_get_next (node);
                   3747:        } /* end while */
                   3748: 
                   3749:        /* now, for all childs, try to look for the node */
                   3750:        node = axl_node_get_first_child (parent);
                   3751:        while (node != NULL) {
                   3752:                /* make the search */
                   3753:                child = axl_node_find_called (node, name);
                   3754:                
                   3755:                /* child found, return the reference */
                   3756:                if (child != NULL)
                   3757:                        return child;
                   3758:                
                   3759:                /* get next */
                   3760:                node = axl_node_get_next (node);
                   3761:        } /* end while */
                   3762: 
                   3763:        /* child note found */
                   3764:        return NULL;
                   3765: }
                   3766: 
                   3767: /** 
                   3768:  * @brief Allows to get the child that is located at the given
                   3769:  * position, inside the given parent node.
                   3770:  *
                   3771:  * @param parent The parent node where the child will be looked up.
                   3772:  *
                   3773:  * @param position The position where the child will be looked up. The
                   3774:  * values for the position ranges from 0 up to (N - 1).
                   3775:  * 
                   3776:  * @return A reference to the child node \ref axlNode or NULL if fails. 
                   3777:  */
                   3778: axlNode * axl_node_get_child_nth      (axlNode * parent, int position)
                   3779: {
                   3780:        int       iterator;
                   3781:        axlItem * item;
                   3782: 
                   3783:        /* perform some environment checks */
                   3784:        axl_return_val_if_fail (parent, NULL);
                   3785: 
                   3786:        /* check for first reference */
                   3787:        if (parent->first == NULL) {
                   3788:                return NULL;
                   3789:        }
                   3790: 
                   3791:        /* get the first item */
                   3792:        item = parent->first;
                   3793: 
                   3794:        /* get the first node found */
                   3795:        iterator = 0;
                   3796:        while (item != NULL) {
                   3797:                /* check the item type */
                   3798:                if (axl_item_get_type (item) == ITEM_NODE) {
                   3799:                        if (iterator == position) {
                   3800:                                return item->data;
                   3801:                        } else
                   3802:                                iterator++;
                   3803:                } /* end if */
                   3804: 
                   3805:                /* get the next */
                   3806:                item = item->next;
                   3807: 
                   3808:        } /* end while */
                   3809: 
                   3810:        /* no first child found */
                   3811:        return NULL;
                   3812: }
                   3813: 
                   3814: /** 
                   3815:  * @brief Allows to get the number of childs that the provided node
                   3816:  * has.
                   3817:  * 
                   3818:  * @param parent The node where the number of childs is being queried.
                   3819:  * 
                   3820:  * @return The number of childs or -1 if fails.
                   3821:  */
                   3822: int       axl_node_get_child_num      (axlNode * parent)
                   3823: {
                   3824:        int       count;
                   3825:        axlItem * item;
                   3826: 
                   3827:        /* perform some environment checks */
                   3828:        axl_return_val_if_fail (parent, -1);
                   3829: 
                   3830:        /* init values */
                   3831:        count = 0;
                   3832:        item  = parent->first;
                   3833: 
                   3834:        /* for each child inside the parent node */
                   3835:        while (item != NULL) {
                   3836:                
                   3837:                /* check item type */
                   3838:                if (axl_item_get_type (item) == ITEM_NODE)
                   3839:                        count++;
                   3840:                
                   3841:                /* get the next */
                   3842:                item = item->next;
                   3843: 
                   3844:        } /* end while */
                   3845: 
                   3846:        /* return the number of chils */
                   3847:        return count;
                   3848: }
                   3849: 
                   3850: 
                   3851: /** 
                   3852:  * @brief Allows to get childs nodes from the given xml node (\ref
                   3853:  * axlNode).
                   3854:  *
                   3855:  * This function creates a newly allocated list. In the case you want
                   3856:  * to iterate over all nodes, it is better to use something similar to
                   3857:  * this:
                   3858:  *
                   3859:  * \code
                   3860:  * axlNode * child;
                   3861:  *
                   3862:  * // get the first child 
                   3863:  * child = axl_node_get_first_child (parent);
                   3864:  * 
                   3865:  * // iterate over all nodes 
                   3866:  * while (child != NULL) {
                   3867:  *
                   3868:  *    // do something with the child 
                   3869:  *    do_some_work (child);
                   3870:  * 
                   3871:  *    // update the reference to the next child
                   3872:  *    child = axl_node_get_next (child);   
                   3873:  * }
                   3874:  * \endcode
                   3875:  *
                   3876:  * @param node The node where the childs will be returned.
                   3877:  * 
                   3878:  * @return An \ref axlList containing \ref axlNode items or NULL if it
                   3879:  * fails. The list returned MUST be deallocated.
                   3880:  */
                   3881: axlList * axl_node_get_childs         (axlNode * node)
                   3882: {
                   3883:        axlItem * child;
                   3884:        axlList * result;
                   3885: 
                   3886:        axl_return_val_if_fail (node, NULL);
                   3887:        
                   3888:        /* create the result list without destroy function */
                   3889:        result  = axl_list_new (__axl_node_equal, NULL);
                   3890:        
                   3891:        /* get the first child */
                   3892:        child = node->first;
                   3893: 
                   3894:        while (child != NULL) {
                   3895:                /* check the node type */
                   3896:                if (axl_item_get_type (child) == ITEM_NODE) {
                   3897:                        /* add the child to the list */
                   3898:                        axl_list_add (result, child->data);
                   3899:                        
                   3900:                } /* end if */
                   3901: 
                   3902:                /* update the reference to the next child */
                   3903:                child = child->next;
                   3904:        } /* end while */
                   3905: 
                   3906:        /* return current childs */
                   3907:        return result;
                   3908: }
                   3909: 
                   3910: axl_bool __axl_node_are_equal_attr (axlPointer key, 
                   3911:                                    axlPointer value, 
                   3912:                                    axlPointer user_data, 
                   3913:                                    axlPointer user_data2)
                   3914: {
                   3915:        char                * value2;
                   3916:        axl_bool                * result = user_data2;
                   3917:        
                   3918:        /* get the attr value and compare it with data */
                   3919:        value2 = axl_hash_get ((axlHash *) user_data, (char *) key);
                   3920: 
                   3921:        if (! axl_cmp ((char *) value, value2)) {
                   3922:                /* flag that node attributes aren't equal */
                   3923:                (* result) = axl_false;
                   3924: 
                   3925:                /* stop foreach */
                   3926:                return axl_true;
                   3927:        }
                   3928:                        
                   3929:        /* make the process to continue */
                   3930:        return axl_false;
                   3931: }
                   3932: 
                   3933: /** 
                   3934:  * @brief Allows to check if the provided references represents two
                   3935:  * equivalent nodes.
                   3936:  *
                   3937:  * The function will check node name, node content and node attributes
                   3938:  * and its values.
                   3939:  * 
                   3940:  * @param node The node to check.
                   3941:  * @param node2 The second node to check.
                   3942:  * @param error Optional reference to an \ref axlError where the particular differ is reported.
                   3943:  * 
                   3944:  * @return axl_true if both nodes are equivalent or axl_false if not.
                   3945:  */
                   3946: axl_bool          axl_node_are_equal_full          (axlNode * node, axlNode * node2, axlError ** error)
                   3947: {
                   3948:        axl_bool result;
                   3949:        
                   3950:        if (node == NULL) {
                   3951:                axl_error_report (error, -1, "Nodes differs because first node reference is NULL");
                   3952:                return axl_false;
                   3953:        } /* end if */
                   3954:        if (node2 == NULL) {
                   3955:                axl_error_report (error, -1, "Nodes differs because second node reference is NULL");
                   3956:                return axl_false;
                   3957:        } /* end if */
                   3958: 
                   3959:        /* check document root name */
                   3960:        if (! axl_cmp (axl_node_get_name (node), axl_node_get_name (node2))) {
                   3961:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node names aren't equal <%s> != <%s>",
                   3962:                           node->name, node2->name);
                   3963:                axl_error_report (error, -1, "node names aren't equal <%s> != <%s>",
                   3964:                                  node->name, node2->name);
                   3965:                return axl_false;
                   3966:        }
                   3967: 
                   3968:        /* check empty ness configuration */
                   3969:        if (axl_node_is_empty (node) != axl_node_is_empty (node2)) {
                   3970:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "emptyness configuration differs <%s> != <%s>",
                   3971:                           node->name, node2->name);
                   3972: 
                   3973:                axl_error_report (error, -1, "emptyness configuration differs <%s> != <%s>",
                   3974:                                  node->name, node2->name);
                   3975:                return axl_false;
                   3976:        }
                   3977:        
                   3978:        /* check childs configuration */
                   3979:        if (axl_node_have_childs (node) != axl_node_have_childs (node2)) {
                   3980:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "childs configuration differs <%s> != <%s>",
                   3981:                           node->name, node2->name);
                   3982:                axl_error_report (error, -1, "childs configuration differs <%s> != <%s>",
                   3983:                                  node->name, node2->name);
                   3984:                return axl_false;
                   3985:        }
                   3986: 
                   3987:        /* check childs number */
                   3988:        if (axl_node_get_child_num (node) != axl_node_get_child_num (node2)) {
                   3989:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child number differs <%s>(%d) != <%s>(%d)",
                   3990:                           node->name, axl_node_get_child_num (node), node2->name, axl_node_get_child_num (node2));
                   3991:                axl_error_report (error, -1, "childs configuration differs <%s> != <%s>",
                   3992:                                  node->name, node2->name);
                   3993:                return axl_false;
                   3994:        }
                   3995: 
                   3996:        /* check attribute values */
                   3997:        if ((node->attributes != NULL && node2->attributes != NULL)) {
                   3998: 
                   3999:                /* check the number of attributes that has the hash */
                   4000:                if (node->attr_num != node2->attr_num) {
                   4001:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "both nodes have different number of attributes (<%s>:%d != <%s>:%d)",
                   4002:                                   node->name, node->attr_num, 
                   4003:                                   node2->name, node2->attr_num);
                   4004:                        axl_error_report (error, -1, "both nodes have different number of attributes (<%s>:%d != <%s>:%d)",
                   4005:                                   node->name, node->attr_num, 
                   4006:                                   node2->name, node2->attr_num);
                   4007:                        return axl_false;
                   4008:                }
                   4009: 
                   4010:                /* now both hashes */
                   4011:                result = axl_true;
                   4012:                if (node->attr_num <= 10) {
                   4013:                        /* check both list are equal */
                   4014:                        result = __axl_node_attr_list_is_equal ((axlNodeAttr *) node->attributes, (axlNodeAttr *) node2->attributes);
                   4015:                } else {
                   4016:                        /* check both hashes are equal */
                   4017:                        axl_hash_foreach2 ((axlHash *) node->attributes, __axl_node_are_equal_attr, (axlHash *) node2->attributes, &result);
                   4018:                }
                   4019: 
                   4020:                if (! result) {
                   4021:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node attributes differs <%s> != <%s>",
                   4022:                                   node->name, node2->name);
                   4023:                        axl_error_report (error, -1, "node attributes differs <%s> != <%s>",
                   4024:                                          node->name, node2->name);
                   4025:                        /* attribute missmatch */
                   4026:                        return axl_false;
                   4027:                }
                   4028:        } else {
                   4029:                if (node->attributes == NULL && node2->attributes != NULL) {
                   4030:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node <%s> has no attributes but <%s> has",
                   4031:                                   axl_node_get_name (node), axl_node_get_name (node2));
                   4032:                        axl_error_report (error, -1, "node <%s> has no attributes but <%s> has",
                   4033:                                          axl_node_get_name (node), axl_node_get_name (node2));
                   4034:                        return axl_false;
                   4035:                }
                   4036: 
                   4037:                if (node2->attributes == NULL && node->attributes != NULL) {
                   4038:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node <%s> has no attributes but <%s> has",
                   4039:                                   axl_node_get_name (node2), axl_node_get_name (node));
                   4040:                        axl_error_report (error, -1, "node <%s> has no attributes but <%s> has",
                   4041:                                          axl_node_get_name (node2), axl_node_get_name (node));
                   4042:                        return axl_false;
                   4043:                }
                   4044: 
                   4045:        } /* end if */
                   4046: 
                   4047:        /* both nodes seems to be equal */
                   4048:        return axl_true;
                   4049: }
                   4050: 
                   4051: /** 
                   4052:  * @brief Allows to check if the provided references represents two
                   4053:  * equivalent nodes.
                   4054:  *
                   4055:  * The function will check node name, node content and node attributes
                   4056:  * and its values.
                   4057:  * 
                   4058:  * @param node The node to check.
                   4059:  * @param node2 The second node to check.
                   4060:  * 
                   4061:  * @return axl_true if both nodes are equivalent or axl_false if not.
                   4062:  */
                   4063: axl_bool          axl_node_are_equal          (axlNode * node, axlNode * node2)
                   4064: {
                   4065:        /* use common implementation */
                   4066:        return axl_node_are_equal_full (node, node2, NULL);
                   4067: }
                   4068: 
                   4069: /** 
                   4070:  * @brief Allows to associate a PI element, including its content to
                   4071:  * the provided node.
                   4072:  *
                   4073:  * See the following function for more information: \ref
                   4074:  * axl_doc_add_pi_target.
                   4075:  *
                   4076:  * @param node The \ref axlNode where the PI element (\ref axlPI) will
                   4077:  * be added.
                   4078:  *
                   4079:  * @param target The PI target name to add.
                   4080:  *
                   4081:  * @param content Optional PI content.
                   4082:  */
                   4083: void      axl_node_add_pi_target            (axlNode * node, 
                   4084:                                             char * target, 
                   4085:                                             char * content)
                   4086: {
                   4087:        axlPI   * pi;
                   4088: 
                   4089:        /* perform some environmental checks */
                   4090:        axl_return_if_fail (node);
                   4091:        axl_return_if_fail (target);
                   4092: 
                   4093:        /* create the PI element */
                   4094:        pi = axl_pi_create (target, content);
                   4095: 
                   4096:        /* set the new process instruction found */
                   4097:        axl_item_set_child (node, ITEM_PI, pi);
                   4098: 
                   4099:        return;
                   4100: }
                   4101: 
                   4102: 
                   4103: /** 
                   4104:  * @brief Allows to check if the provided Processing instruction
                   4105:  * target is defined on the given xml node document (\ref axlNode).
                   4106:  *
                   4107:  * Processing instruction are a way to configure the xml node document
                   4108:  * with processing information to instruct the application level that
                   4109:  * is going to consume the XML information.
                   4110:  *
                   4111:  * @param node The \ref axlNode where the processing instruction will
                   4112:  * be read.
                   4113:  *
                   4114:  * @param pi_target The process instruction name.
                   4115:  * 
                   4116:  * @return axl_true is the processing instruction is defined,
                   4117:  * otherwise axl_false is returned.
                   4118:  */
                   4119: axl_bool          axl_node_has_pi_target            (axlNode * node, 
                   4120:                                                     char    * pi_target)
                   4121: {
                   4122:        axlPI   * pi;
                   4123:        axlItem * item;
                   4124:        
                   4125:        axl_return_val_if_fail (node,      axl_false);
                   4126:        axl_return_val_if_fail (pi_target, axl_false);
                   4127: 
                   4128:        /* assume the pi target doesn't exist if it is not
                   4129:         * initialized */
                   4130:        item = node->first;
                   4131:        while (item != NULL) {
                   4132:                
                   4133:                /* check the type */
                   4134:                if (axl_item_get_type (item) == ITEM_PI) {
                   4135:                        /* get a reference */
                   4136:                        pi = item->data;
                   4137: 
                   4138:                        /* only check the first ocurrency */
                   4139:                        if (axl_cmp (axl_pi_get_name (pi), pi_target))
                   4140:                                return axl_true;
                   4141:                } /* end if */
                   4142: 
                   4143:                /* get the next item */
                   4144:                item = item->next;
                   4145: 
                   4146:        } /* end while */
                   4147: 
                   4148:        return axl_false;
                   4149: }
                   4150: 
                   4151: /** 
                   4152:  * @brief Allows to get current processing instruction content.
                   4153:  * 
                   4154:  * @param node The document where the processing instruction is placed.
                   4155:  *
                   4156:  * @param pi_target The processing instruction target to get current
                   4157:  * content.
                   4158:  * 
                   4159:  * @return An internal reference to the process instruction target
                   4160:  * content. Value returned mustn't be deallocated
                   4161:  */
                   4162: char    * axl_node_get_pi_target_content    (axlNode * node, 
                   4163:                                            char * pi_target)
                   4164: {
                   4165:        axlPI   * pi;
                   4166:        axlItem * item;
                   4167:        
                   4168:        axl_return_val_if_fail (node,      NULL);
                   4169:        axl_return_val_if_fail (pi_target, NULL);
                   4170: 
                   4171:        /* assume the pi target doesn't exist if it is not
                   4172:         * initialized */
                   4173:        item = node->first;
                   4174:        while (item != NULL) {
                   4175:                
                   4176:                /* check the type */
                   4177:                if (axl_item_get_type (item) == ITEM_PI) {
                   4178:                        /* get a reference */
                   4179:                        pi = item->data;
                   4180: 
                   4181:                        /* only check the first ocurrency */
                   4182:                        if (axl_cmp (axl_pi_get_name (pi), pi_target))
                   4183:                                return axl_pi_get_content (pi);
                   4184:                } /* end if */
                   4185: 
                   4186:                /* get the next item */
                   4187:                item = item->next;
                   4188: 
                   4189:        } /* end while */
                   4190: 
                   4191:        return NULL;
                   4192: }
                   4193: 
                   4194: /** 
                   4195:  * @brief Allows to transfer (move from) all childs (including
                   4196:  * comments, content, PI, nodes, etc) from the old parent to the new
                   4197:  * parent.
                   4198:  *
                   4199:  * This function is particular useful while moving content from nodes.
                   4200:  * 
                   4201:  * @param old_parent The old parent node where all childs will be
                   4202:  * removed and placed in the new parent.
                   4203:  *
                   4204:  * @param new_parent The parent node where the content will be
                   4205:  * placed. If the parent node already have childs, the content will be
                   4206:  * appended.
                   4207:  */
                   4208: void      axl_node_transfer_childs          (axlNode * old_parent, 
                   4209:                                             axlNode * new_parent)
                   4210: {
                   4211:        axlItem * item;
                   4212:        axlItem * item_aux;
                   4213:        
                   4214:        /* get the first child for the old parent */
                   4215:        item = old_parent->first;
                   4216:        while (item != NULL) {
                   4217: 
                   4218:                /* get a reference to the next before adding */
                   4219:                item_aux = item->next;
                   4220: 
                   4221:                /* set the item to parent for the new node */
                   4222:                axl_item_set_child_ref (new_parent, item);
                   4223: 
                   4224:                
                   4225:                /* get the next */
                   4226:                item = item_aux;
                   4227: 
                   4228:        } /* end while */
                   4229: 
                   4230:        /* clear reference from previous parent */
                   4231:        old_parent->first     = NULL;
                   4232:        old_parent->last      = NULL;
                   4233:        
                   4234:        return;
                   4235: }
                   4236: 
                   4237: /** 
                   4238:  * @internal Implementation for the public API provided to dump node content.
                   4239:  */
                   4240: axl_bool __axl_node_dump_common (axlNode * node, char ** content, int * size, axl_bool pretty_print, int level, int tabular)
                   4241: {
                   4242:        int    _size;
                   4243:        int    index;
                   4244:        char * result;
                   4245: 
                   4246:        /* check refererences received */
                   4247:        axl_return_val_if_fail (node,    axl_false);
                   4248:        axl_return_val_if_fail (content, axl_false);
                   4249: 
                   4250:        /* get dump size */
                   4251:        _size = axl_node_get_flat_size (node, pretty_print, level, tabular);
                   4252: 
                   4253:        /* dump the content */
                   4254:        result = axl_new (char, _size + 1);
                   4255:        index  = axl_node_dump_at (node, result, 0, pretty_print, level, tabular);
                   4256: 
                   4257:        /* check result */
                   4258:        if (index != _size) {
                   4259:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump xml node, size dump operation mismatch: %d != %d", 
                   4260:                           index, _size);
                   4261:                /* free allocated result */
                   4262:                axl_free (result);
                   4263: 
                   4264:                /* nullify content */
                   4265:                if (size)
                   4266:                        *size = -1;
                   4267:                *content      = NULL;
                   4268:                
                   4269:                return axl_false;
                   4270:        } /* end if */
                   4271: 
                   4272:        /* fill the size */
                   4273:        if (size)
                   4274:                *size = _size;
                   4275:        *content      = result;
                   4276: 
                   4277:        /* return content */
                   4278:        return axl_true;
                   4279: }
                   4280: 
                   4281: /** 
                   4282:  * @brief Allows to dump the xml content taking as starting point the
                   4283:  * xml node provided. 
                   4284:  * 
                   4285:  * @param node The \ref axlNode used as reference and starting point
                   4286:  * to dump.
                   4287:  *
                   4288:  * @param content The reference where the result will be returned.
                   4289:  *
                   4290:  * @param size The reference where the document content size will be
                   4291:  * returned. 
                   4292:  *
                   4293:  * @return The function returns \ref axl_true if the dump operation
                   4294:  * was performed. Otherwise \ref axl_false is returned.
                   4295:  */
                   4296: axl_bool      axl_node_dump                    (axlNode  * node, 
                   4297:                                                char    ** content, 
                   4298:                                                int      * size)
                   4299: {
                   4300:        /* use common implementation for all functions */
                   4301:        return __axl_node_dump_common (node, content, size, axl_false, 0, 0);
                   4302: }
                   4303: 
                   4304: /** 
                   4305:  * @brief Allows to perform a pretty print operation using as
                   4306:  * reference (starting point) the node provided.
                   4307:  * 
                   4308:  * @param node The node to be used as reference for the dump operation.
                   4309:  * 
                   4310:  * @param content A reference to a user defined pointer where the
                   4311:  * content will be placed. Non optional parameter.
                   4312:  *
                   4313:  * @param size A reference to a user defined pointer where the content
                   4314:  * size will be placed. Optional parameter.
                   4315:  * 
                   4316:  * @param tabular How many spaces to be placed on each level.
                   4317:  * 
                   4318:  * @return \ref axl_true if the dump operation was properly done, otherwise
                   4319:  * \ref axl_false is returned.
                   4320:  */
                   4321: axl_bool      axl_node_dump_pretty             (axlNode  * node,
                   4322:                                                char    ** content,
                   4323:                                                int      * size,
                   4324:                                                int        tabular)
                   4325: {
                   4326:        /* use common implementation for all functions */
                   4327:        return __axl_node_dump_common (node, content, size, axl_true, 0, tabular);
                   4328: }
                   4329: 
                   4330: /** 
                   4331:  * @brief Allows to dump the xml document using as reference the node
                   4332:  * provided, at the file path provided.
                   4333:  * 
                   4334:  * @param node The document node reference to use to build the
                   4335:  * content.
                   4336:  *
                   4337:  * @param file_path File path where place the result.
                   4338:  * 
                   4339:  * @return \ref axl_true if the dump operation was done, otherwise \ref axl_false is
                   4340:  * returned.
                   4341:  */
                   4342: axl_bool      axl_node_dump_to_file            (axlNode  * node,
                   4343:                                                char     * file_path)
                   4344: {
                   4345:        char * content;
                   4346:        int    size;
                   4347:        FILE * fd;
                   4348:        int    written;
                   4349: 
                   4350:        /* use common implementation for all functions */
                   4351:        if (!  __axl_node_dump_common (node, &content, &size, axl_true, 0, 0))
                   4352:                return axl_false;
                   4353: 
                   4354:        /* open the file and check */
                   4355: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   4356:        if (fopen_s (&fd, file_path, "w") != 0) {
                   4357: #else
                   4358:        if ((fd = fopen (file_path, "w")) == NULL) {
                   4359: #endif
                   4360:                /* failed to open the file to dump the content */
                   4361:                axl_free (content);
                   4362: 
                   4363:                return axl_false;
                   4364:        }
                   4365: 
                   4366:        /* dump the content */
                   4367:        written = fwrite (content, 1, size, fd);
                   4368: 
                   4369:        /* free the content */
                   4370:        axl_free (content);
                   4371: 
                   4372:        /* close file */
                   4373:        fclose (fd);
                   4374: 
                   4375:        /* return if we have failed to dump all the content to the
                   4376:         * file or not. */
                   4377:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   4378:                   (written == size) ? "OK" : "FAILED", 
                   4379:                   written, size);
                   4380:                   
                   4381:        return (written == size);
                   4382:                
                   4383: }
                   4384: 
                   4385: /** 
                   4386:  * @brief Allows to pretty print dump the xml document using as
                   4387:  * reference the node provided, at the file path provided.
                   4388:  * 
                   4389:  * @param node The document node reference to use to build the
                   4390:  * content.
                   4391:  *
                   4392:  * @param file_path File path where place the result.
                   4393:  *
                   4394:  * @param tabular How many spaces to be placed at each level.
                   4395:  * 
                   4396:  * @return \ref axl_true if the dump operation was done, otherwise \ref axl_false is
                   4397:  * returned.
                   4398:  */
                   4399: axl_bool      axl_node_dump_pretty_to_file     (axlNode  * node,
                   4400:                                                char     * file_path,
                   4401:                                                int        tabular)
                   4402: {
                   4403:        char * content;
                   4404:        int    size;
                   4405:        FILE * fd;
                   4406:        int    written;
                   4407: 
                   4408:        /* use common implementation for all functions */
                   4409:        if (!  __axl_node_dump_common (node, &content, &size, axl_true, 0, tabular))
                   4410:                return axl_false;
                   4411: 
                   4412:        /* open the file and check */
                   4413: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   4414:        if (fopen_s (&fd, file_path, "w") != 0) {
                   4415: #else
                   4416:        if ((fd = fopen (file_path, "w")) == NULL) {
                   4417: #endif
                   4418:                /* failed to open the file to dump the content */
                   4419:                axl_free (content);
                   4420: 
                   4421:                return axl_false;
                   4422:        }
                   4423: 
                   4424:        /* dump the content */
                   4425:        written = fwrite (content, 1, size, fd);
                   4426: 
                   4427:        /* free the content */
                   4428:        axl_free (content);
                   4429: 
                   4430:        /* close file */
                   4431:        fclose (fd);
                   4432: 
                   4433:        /* return if we have failed to dump all the content to the
                   4434:         * file or not. */
                   4435:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   4436:                   (written == size) ? "OK" : "FAILED", 
                   4437:                   written, size);
                   4438:                   
                   4439:        return (written == size);
                   4440: }
                   4441: 
                   4442: /** 
                   4443:  * @brief Allows to get a list which contains \ref axlPI nodes,
                   4444:  * representing all process instruction that the \ref axlNode (xml
                   4445:  * document node) has.
                   4446:  *
                   4447:  * While using PI, you can use the following functions to get PI
                   4448:  * information:
                   4449:  * 
                   4450:  *  - \ref axl_node_has_pi_target
                   4451:  *  - \ref axl_node_get_pi_target_content
                   4452:  *
                   4453:  * However, this function will return first ocurrence for PI found
                   4454:  * inside the xml document. If you don't use repeated PI elements, you
                   4455:  * won't find problems, but, if you need to iterate ever all PI found
                   4456:  * or you are using repeated PI, you can use this function as follows
                   4457:  * to get current pi elements:
                   4458:  *
                   4459:  * \code
                   4460:  * void show_all_pi (axlNode * node) 
                   4461:  * {
                   4462:  *      int       iterator;
                   4463:  *      axlPI   * pi;
                   4464:  *      axlList * PIs;
                   4465:  *
                   4466:  *      // get all PI target that the node has
                   4467:  *      PIs      = axl_node_get_pi_target_list (node);
                   4468:  *      iterator = 0;
                   4469:  *
                   4470:  *      while (iterator < axl_list_length (PIs)) {
                   4471:  *            // get next pi stored 
                   4472:  *            pi = axl_list_get_nth (PIs, iterator);
                   4473:  *
                   4474:  *            // do some stuff 
                   4475:  *            printf ("PI found target name=%s, content=%s\n",
                   4476:  *                    axl_pi_get_name (pi),
                   4477:  *                    axl_pi_get_content (pi));
                   4478:  *            
                   4479:  *            // update the iterator
                   4480:  *            iterator++;
                   4481:  *      }
                   4482:  *
                   4483:  *      // once finished, free the list 
                   4484:  *      axl_list_free (PIs);
                   4485:  *      return;
                   4486:  * }
                   4487:  * \endcode
                   4488:  * 
                   4489:  * @param node The xml node (\ref axlNode) where the process
                   4490:  * instruction will be returned.
                   4491:  * 
                   4492:  * @return A reference to the list of processing instruction that the
                   4493:  * xml node (\ref axlNode) has. The returned list, if defined, must be
                   4494:  * deallocated.
                   4495:  */
                   4496: axlList * axl_node_get_pi_target_list       (axlNode * node)
                   4497: {
                   4498:        axlList * result = NULL;
                   4499:        axlItem * item;
                   4500:        
                   4501:        axl_return_val_if_fail (node, NULL);
                   4502: 
                   4503:        /* assume the pi target doesn't exist if it is not
                   4504:         * initialized */
                   4505:        item = node->first;
                   4506:        while (item != NULL) {
                   4507:                
                   4508:                /* check the type */
                   4509:                if (axl_item_get_type (item) == ITEM_PI) {
                   4510:                        /* create the result list */
                   4511:                        if (result == NULL)
                   4512:                                result = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_pi_free);  
                   4513: 
                   4514:                        /* add the list */
                   4515:                        axl_list_add (result, item->data);
                   4516:                        
                   4517:                } /* end if */
                   4518: 
                   4519:                /* get the next item */
                   4520:                item = item->next;
                   4521: 
                   4522:        } /* end while */
                   4523: 
                   4524:        return result;
                   4525: }
                   4526: 
                   4527: axl_bool __axl_node_get_flat_size_attributes_foreach (axlPointer attr, 
                   4528:                                                      axlPointer value, 
                   4529:                                                      axlPointer user_data)
                   4530: {
                   4531:        int * length = user_data;
                   4532: 
                   4533:        /* " attribute='value' */
                   4534:        (*length) += 4 + strlen ((char*) attr) + strlen ((char*) value);
                   4535: 
                   4536:        /* make the process to continue */
                   4537:        return axl_false;
                   4538: }
                   4539: 
                   4540: /** 
                   4541:  * @internal
                   4542:  * @brief Returns the space required to write the attribute part.
                   4543:  */
                   4544: int __axl_node_get_flat_size_attributes (axlNode * node)
                   4545: {
                   4546: 
                   4547:        int            length = 0;
                   4548:        axlNodeAttr  * attr   = NULL;
                   4549:        
                   4550:        /* if attribute list is not defined just return 0 */
                   4551:        if (node->attributes == NULL)
                   4552:                return 0;
                   4553: 
                   4554:        /* perform a foreach and accumulate */
                   4555:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "get flat size for node <%s>", 
                   4556:                   axl_node_get_name (node));
                   4557:        if (node->attr_num <= 10) {
                   4558:                /* get the first reference */
                   4559:                attr = (axlNodeAttr *) node->attributes;
                   4560:                while (attr != NULL) {
                   4561:                        /* call to get length */
                   4562:                        __axl_node_get_flat_size_attributes_foreach (attr->attribute, attr->value, &length);
                   4563:                        
                   4564:                        /* get the next */
                   4565:                        attr = attr->next;
                   4566:                }
                   4567:                
                   4568:        } else {
                   4569:                /* perform a foreach */
                   4570:                axl_hash_foreach ((axlHash *) node->attributes, __axl_node_get_flat_size_attributes_foreach, &length);
                   4571:        }
                   4572: 
                   4573:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "after foreach flat size for node <%s> is %d", 
                   4574:                   axl_node_get_name (node), length);
                   4575: 
                   4576:        /* return the length */
                   4577:        return length;
                   4578: }
                   4579: 
                   4580: /** 
                   4581:  * @internal
                   4582:  *
                   4583:  * Returns which the size that the node and its childs will hold if
                   4584:  * the are represented into a flat xml stream.
                   4585:  * 
                   4586:  * @param node The node that is requested its stream xml size.
                   4587:  *
                   4588:  * @param pretty_print If pretty print is activated.
                   4589:  *
                   4590:  * @param level Which is the relative level of the node respected to
                   4591:  * the root node.
                   4592:  * 
                   4593:  * @return The stream size or -1 if fails.
                   4594:  */
                   4595: int       axl_node_get_flat_size            (axlNode * node, axl_bool pretty_print, int level, int tabular)
                   4596: {
                   4597:        int              result    = 0;
                   4598:        axlItem        * item;
                   4599:        axlNodeContent * content;
                   4600:        axl_bool         is_empty;
                   4601:        axl_bool         have_childs;
                   4602: 
                   4603:        axl_return_val_if_fail (node, -1);
                   4604: 
                   4605:        /* get values */
                   4606:        is_empty    = axl_node_is_empty (node);
                   4607:        have_childs = axl_node_have_childs_aux (node);
                   4608: 
                   4609:        if (have_childs || (!have_childs && !is_empty)) {
                   4610:                /* the node is emtpy because it has no content but it has
                   4611:                 * childs:
                   4612:                 *
                   4613:                 * "<" + strlen (node-name) + ">" + ... + "</" + strlen (node-name) + ">" */
                   4614:                result = 5 + (2 * strlen (node->name)) + __axl_node_get_flat_size_attributes (node);
                   4615:                
                   4616:                /* check pretty_print */
                   4617:                if (pretty_print) {
                   4618:                        /* two tabulations plus two carry return \r\n
                   4619:                         * on windows and \n on unix */
                   4620:                        if (have_childs) 
                   4621:                                result += (level * tabular * 2) + 2; 
                   4622:                        else
                   4623:                                result += (level * tabular) + 1; 
                   4624: #ifdef __AXL_OS_WIN32__
                   4625:                        if (have_childs)
                   4626:                                result += 2;
                   4627:                        else
                   4628:                                result ++;
                   4629: #endif
                   4630:                }
                   4631:        } else {
                   4632:                if (is_empty) {
                   4633:                        /* "<" + strlen (node-name) + " />" */
                   4634:                        result = strlen (node->name) + 4 + __axl_node_get_flat_size_attributes (node);
                   4635:                        
                   4636:                        /* check pretty print */
                   4637:                        if (pretty_print) {
                   4638:                                /* one tabular plus one carry return
                   4639:                                 * \r\n on windows and \n on unix */
                   4640:                                result += (level * tabular) + 1;
                   4641: #ifdef __AXL_OS_WIN32__
                   4642:                                result += 1;
                   4643: #endif
                   4644:                        }
                   4645:                        
                   4646:                        /* return sum */
                   4647:                        return result;
                   4648:                }
                   4649:        }
                   4650: 
                   4651:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node=<%s> count=%d", node->name, result);
                   4652:        
                   4653:        /* get first child */
                   4654:        item = node->first;
                   4655:        while (item != NULL) {
                   4656:                /* according to the type, check a size */
                   4657:                switch (axl_item_get_type (item)) {
                   4658:                case ITEM_NODE:
                   4659:                        /* count how many bytes the node holds */
                   4660:                        result += axl_node_get_flat_size (item->data, pretty_print, level + 1, tabular);
                   4661:                        break;
                   4662:                case ITEM_CONTENT:
                   4663:                        /* content */
                   4664:                        content = (axlNodeContent *) item->data;
                   4665:                        result += content->content_size;
                   4666:                        break;
                   4667:                case ITEM_CDATA:
                   4668:                        /* content + '<![CDATA[' + ']]>' */
                   4669:                        content = (axlNodeContent *) item->data;
                   4670:                        result += content->content_size + 12;
                   4671:                        break;
                   4672:                case ITEM_PI:
                   4673:                        /* get current size */
                   4674:                        result += axl_pi_get_size (item->data);
                   4675:                        break;
                   4676:                case ITEM_COMMENT:
                   4677:                        /* content + '<!-- ' + ' -->' */
                   4678:                        content = (axlNodeContent *) item->data;
                   4679: 
                   4680:                        /* check if the content has already defined white spaces */
                   4681:                        if (content->content[0] == ' ' && content->content[content->content_size - 1] == ' ')
                   4682:                                result += content->content_size + 7;
                   4683:                        else if (content->content[0] != ' ' && content->content[content->content_size - 1] == ' ')
                   4684:                                result += content->content_size + 8;
                   4685:                        else if (content->content[0] == ' ' && content->content[content->content_size - 1] != ' ')
                   4686:                                result += content->content_size + 8;
                   4687:                        else
                   4688:                                result += content->content_size + 9;
                   4689:                        if (pretty_print) {
                   4690:                                /* tabular indent + \n */
                   4691:                                result += ((level + 1) * tabular) + 1;
                   4692: #ifdef __AXL_OS_WIN32__
                   4693:                                /* \r\n */
                   4694:                                result += 1;
                   4695: #endif
                   4696:                        }
                   4697: 
                   4698:                        break;
                   4699:                case ITEM_REF:
                   4700:                        /* item ref + '&' + ';' */
                   4701:                        content = (axlNodeContent *) item->data;
                   4702:                        result += content->content_size + 2;
                   4703:                        break;
                   4704:                case ITEM_FROM_FACTORY:
                   4705:                case ITEM_CONTENT_FROM_FACTORY:
                   4706:                        /* never reached */
                   4707:                        break;
                   4708:                }
                   4709:                /* get next item */
                   4710:                item = item->next;
                   4711:                        
                   4712:        } /* end while */
                   4713:                
                   4714:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child processing finished for: parent=<%s>, count=%d", node->name, result);
                   4715: 
                   4716:        /* return the result */
                   4717:        return result;
                   4718: }
                   4719: 
                   4720: axl_bool __axl_node_dump_attributes_at_foreach (axlPointer key, 
                   4721:                                                axlPointer value, 
                   4722:                                                axlPointer user_data,
                   4723:                                                axlPointer user_data2)
                   4724: {
                   4725:        char      * content    = user_data;
                   4726:        int       * _desp      = user_data2;
                   4727:        axl_bool    terminator = axl_false;
                   4728:        int         desp       = (*_desp);
                   4729:        int         length;
                   4730: 
                   4731:        memcpy (content + desp, " ", 1);
                   4732:        desp += 1;
                   4733:        
                   4734:        length = strlen ((char*) key);
                   4735:        memcpy (content + desp, (char *) key, length);
                   4736:        desp += length;
                   4737: 
                   4738:        /* check if the content contains a ' so, enclose the attribute
                   4739:         * with " */
                   4740:        if (strstr (value, "'") == NULL) {
                   4741:                memcpy (content + desp, "='", 2);
                   4742:                desp += 2;
                   4743:        }else {
                   4744:                terminator = axl_true;
                   4745:                memcpy (content + desp, "=\"", 2);
                   4746:                desp += 2;
                   4747:        }
                   4748:        
                   4749:        length = strlen ((char*) value);
                   4750:        memcpy (content + desp, (char*) value, length);
                   4751:        desp += length;
                   4752: 
                   4753:        /* dump attribute termination */
                   4754:        if (terminator) {
                   4755:                memcpy (content + desp, "\"", 1);
                   4756:        }else {
                   4757:                memcpy (content + desp, "'", 1);                
                   4758:        }
                   4759:        desp += 1;
                   4760: 
                   4761:        /* update desp */
                   4762:        (*_desp) = desp;
                   4763: 
                   4764:        /* make the process to continue */
                   4765:        return axl_false;
                   4766: }
                   4767: 
                   4768: void __axl_node_dump_at_the_end (axlNodeAttr * attr, char * content, int * desp)
                   4769: {
                   4770:        /* return if no attribute must be dumped */
                   4771:        if (attr == NULL)
                   4772:                return;
                   4773: 
                   4774:        /* call to dump next attributes first */
                   4775:        __axl_node_dump_at_the_end (attr->next, content, desp);
                   4776: 
                   4777:        /* now dump our attribute */
                   4778:        __axl_node_dump_attributes_at_foreach (attr->attribute, attr->value, content, desp);
                   4779: 
                   4780:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping attribute: %s=%s", attr->attribute, attr->value);
                   4781: 
                   4782:        return;
                   4783: }
                   4784: 
                   4785: /** 
                   4786:  * @internal
                   4787:  * 
                   4788:  * Internal support function which dumps current attribute
                   4789:  * configuration into the given memory using the provided desp.
                   4790:  */
                   4791: int axl_node_dump_attributes_at (axlNode * node, char * content, int desp)
                   4792: {
                   4793:        axlNodeAttr  * attr   = NULL;   
                   4794: 
                   4795:        /* if attribute list is not defined just return 0 */
                   4796:        if (node->attributes == NULL)
                   4797:                return desp;
                   4798: 
                   4799:        /* according to the attribute num */
                   4800:        if (node->attr_num <= 10) {
                   4801:                /* get the first reference */
                   4802:                attr = (axlNodeAttr *) node->attributes;
                   4803:                __axl_node_dump_at_the_end (attr, content, &desp);
                   4804: 
                   4805:        } else {
                   4806:                /* foreach attribute dump */
                   4807:                axl_hash_foreach2 ((axlHash *) node->attributes, __axl_node_dump_attributes_at_foreach, content, &desp);
                   4808:        }
                   4809: 
                   4810:        /* return the length */
                   4811:        return desp;
                   4812: }
                   4813: 
                   4814: /** 
                   4815:  * @internal Writes the indentation according to the tabular size and
                   4816:  * the indent level.
                   4817:  * 
                   4818:  * @param content The reference to the content where the dump
                   4819:  * operation will be performed.
                   4820:  *
                   4821:  * @param tabular The tabular size to be applied for each level.
                   4822:  *
                   4823:  * @param level The indent level to be applied.
                   4824:  * 
                   4825:  * @return The number of bytes written.
                   4826:  */
                   4827: int __axl_node_dump_at_write_indent (char * content, int tabular, int level)
                   4828: {
                   4829:        int iterator = 0;
                   4830: 
                   4831:        while (iterator < (tabular * level)) {
                   4832:                /* write tabular info */
                   4833:                memcpy (content + iterator, " ", 1);
                   4834:                
                   4835:                /* update iterator */
                   4836:                iterator++;
                   4837:        } /* end while */
                   4838: 
                   4839:        return iterator;
                   4840: }
                   4841:        
                   4842: /* dump content */
                   4843: int __axl_node_dump_items (axlItem * item, char * content, int level, axl_bool pretty_print, int desp, int tabular)
                   4844: {
                   4845: 
                   4846:        axlNodeContent * nodeContent;
                   4847:        char           * string_aux;
                   4848: 
                   4849:        /* get first child */
                   4850:        while (item != NULL) {
                   4851:                /* according to the type, check a size */
                   4852:                switch (axl_item_get_type (item)) {
                   4853:                case ITEM_NODE:
                   4854:                        /* write axl node content */
                   4855:                        desp  = axl_node_dump_at (item->data, content, desp, pretty_print, level + 1, tabular);
                   4856:                        break;
                   4857:                case ITEM_CONTENT:
                   4858:                        /* write content information */
                   4859:                        nodeContent = (axlNodeContent *)item->data;
                   4860:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4861:                        desp += nodeContent->content_size;
                   4862:                        break;
                   4863:                case ITEM_CDATA:
                   4864:                        /* write content information */
                   4865:                        nodeContent = (axlNodeContent *)item->data;
                   4866:                        
                   4867:                        /* write cdata content */
                   4868:                        memcpy (content + desp, "<![CDATA[", 9);
                   4869:                        desp += 9;
                   4870:                        
                   4871:                        /* write content */
                   4872:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4873:                        desp += nodeContent->content_size;
                   4874:                        
                   4875:                        /* write cdata end */
                   4876:                        memcpy (content + desp, "]]>", 3);
                   4877:                        desp += 3;
                   4878:                        break;
                   4879:                case ITEM_PI:
                   4880:                        /* write pi start */
                   4881:                        memcpy (content + desp, "<?", 2);
                   4882:                        desp += 2;
                   4883:                        
                   4884:                        /* write pi name */
                   4885:                        string_aux = axl_pi_get_name (item->data);
                   4886:                        memcpy (content + desp, string_aux, strlen (string_aux));
                   4887:                        desp += strlen (string_aux);
                   4888:                        
                   4889:                        /* write pi start */
                   4890:                        memcpy (content + desp, " ", 1);
                   4891:                        desp += 1;
                   4892:                        
                   4893:                        /* write pi content */
                   4894:                        string_aux = axl_pi_get_content (item->data);
                   4895:                        memcpy (content + desp, string_aux, strlen (string_aux));
                   4896:                        desp += strlen (string_aux);
                   4897:                        
                   4898:                        /* write pi start */
                   4899:                        memcpy (content + desp, "?>", 2);
                   4900:                        desp += 2;
                   4901:                        break;
                   4902:                case ITEM_COMMENT:
                   4903: 
                   4904:                        /* check for pretty print to write indent */
                   4905:                        if (pretty_print) {
                   4906:                                desp += __axl_node_dump_at_write_indent (content + desp, tabular, level + 1);
                   4907:                        }
                   4908: 
                   4909:                        /* get a reference to the content */
                   4910:                        nodeContent = (axlNodeContent *)item->data;
                   4911: 
                   4912:                        /* add an space if the content is found to not
                   4913:                         * have one */
                   4914:                        if (nodeContent->content [0] == ' ') {
                   4915:                                memcpy (content + desp, "<!--", 4);
                   4916:                                desp += 4;
                   4917:                        } else {
                   4918:                                memcpy (content + desp, "<!-- ", 5);
                   4919:                                desp += 5;
                   4920:                        }
                   4921:                        
                   4922: 
                   4923:                        
                   4924:                        /* write content */
                   4925:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4926:                        desp += nodeContent->content_size;
                   4927:                        
                   4928:                        /* add an space if the content is found to not
                   4929:                         * have one */
                   4930:                        if (nodeContent->content [nodeContent->content_size - 1] == ' ') {
                   4931:                                memcpy (content + desp, "-->", 3);
                   4932:                                desp += 3;
                   4933:                        } else {
                   4934:                                memcpy (content + desp, " -->", 4);
                   4935:                                desp += 4;
                   4936:                        } /* end if */
                   4937: 
                   4938:                        if (pretty_print) {
                   4939: #ifdef __AXL_OS_WIN32__
                   4940:                                memcpy (content + desp, "\r\n", 2);
                   4941:                                desp += 2;
                   4942: #else
                   4943:                                memcpy (content + desp, "\n", 1);
                   4944:                                desp += 1;
                   4945: #endif
                   4946:                        }
                   4947: 
                   4948:                        break;
                   4949:                case ITEM_REF:
                   4950:                        /* content + '&' + ';' */
                   4951:                        memcpy (content + desp, "&", 1);
                   4952:                        desp += 1;
                   4953:                        
                   4954:                        /* get a reference to the content */
                   4955:                        nodeContent = (axlNodeContent *)item->data;
                   4956:                        
                   4957:                        /* write content */
                   4958:                        memcpy (content + desp, nodeContent->content, nodeContent->content_size);
                   4959:                        desp += nodeContent->content_size;
                   4960:                        
                   4961:                        memcpy (content + desp, ";", 1);
                   4962:                        desp += 1;
                   4963:                        break;
                   4964:                case ITEM_FROM_FACTORY:
                   4965:                case ITEM_CONTENT_FROM_FACTORY:
                   4966:                        /* never reached */
                   4967:                        break;
                   4968:                }
                   4969:                
                   4970:                /* get next item */
                   4971:                item = item->next;
                   4972:                
                   4973:        } /* end while */
                   4974: 
                   4975:        /* return desp calculated */
                   4976:        return desp;
                   4977: 
                   4978: } /* end __axl_node_dump_items */
                   4979: 
                   4980: /** 
                   4981:  * @internal
                   4982:  *
                   4983:  * Writes the node information represented by the node provided at the
                   4984:  * given position into the buffer provided.
                   4985:  * 
                   4986:  * @param node The node to dump and its childs.
                   4987:  *
                   4988:  * @param content The memory buffer where the content will be dumped.
                   4989:  *
                   4990:  * @param desp A memory desp where to dump the node content inside the
                   4991:  * memory provided.
                   4992:  * 
                   4993:  * @return The new desp value to be used on the next dump.
                   4994:  */
                   4995: int       axl_node_dump_at                  (axlNode * node,
                   4996:                                             char    * content,
                   4997:                                             int       desp,
                   4998:                                             axl_bool  pretty_print,
                   4999:                                             int       level,
                   5000:                                             int       tabular)
                   5001: {
                   5002:        axlItem        * item;
                   5003:        axl_bool         have_childs;
                   5004: 
                   5005:        axl_return_val_if_fail (node, -1);
                   5006: 
                   5007:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping node=<%s> at %d", 
                   5008:                   axl_node_get_name (node), desp);
                   5009: 
                   5010:        /* get current have childs status */
                   5011:        have_childs = axl_node_have_childs_aux (node);
                   5012: 
                   5013:        /* check for pretty print and tabular */
                   5014:        if (pretty_print) {
                   5015:                desp += __axl_node_dump_at_write_indent (content + desp, tabular, level);
                   5016:        } /* end if */
                   5017: 
                   5018:        /* check if the node is empty */
                   5019:        if (axl_node_is_empty (node)) {
                   5020:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node <%s> is empty", 
                   5021:                           axl_node_get_name (node));
                   5022: 
                   5023:                if (! have_childs) {
                   5024:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "dumping an empty node without childs=<%s>",
                   5025:                                   axl_node_get_name (node));
                   5026:                        
                   5027:                        /* "<" + strlen (node-name) + " />" */
                   5028:                        memcpy (content + desp, "<", 1);
                   5029:                        desp += 1;
                   5030: 
                   5031:                        memcpy (content + desp, node->name, strlen (node->name));
                   5032:                        desp += strlen (node->name);
                   5033: 
                   5034:                        /* dump attribute values */
                   5035:                        desp = axl_node_dump_attributes_at (node, content, desp);
                   5036: 
                   5037:                        memcpy (content + desp, " />", 3);
                   5038:                        desp += 3;
                   5039: 
                   5040:                        /* write traling node information */
                   5041:                        if (pretty_print) {
                   5042: #ifdef __AXL_OS_WIN32__
                   5043:                                memcpy (content + desp, "\r\n", 2);
                   5044:                                desp += 2;
                   5045: #else
                   5046:                                memcpy (content + desp, "\n", 1);
                   5047:                                desp += 1;
                   5048: #endif
                   5049:                        }
                   5050: 
                   5051:                        return desp;
                   5052:                }
                   5053:        }
                   5054: 
                   5055:        /* the node is empty because it doesn't have content but it
                   5056:         * has childs 
                   5057:         * "<" + strlen (node-name) + ">" + strlen (node-content) + 
                   5058:         * "</" + strlen (node-name) + ">" */
                   5059:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting content for: <%s>", axl_node_get_name (node));
                   5060: 
                   5061:        /* dump node start tag */
                   5062:        memcpy (content + desp, "<", 1);
                   5063:        desp += 1;
                   5064: 
                   5065:        memcpy (content + desp, node->name, strlen (node->name));
                   5066:        desp += strlen (node->name);
                   5067: 
                   5068:        /* dump attribute values */
                   5069:        desp = axl_node_dump_attributes_at (node, content, desp);
                   5070: 
                   5071:        memcpy (content + desp, ">", 1);
                   5072:        desp += 1;
                   5073: 
                   5074:        /* if the node have childs */
                   5075:        if (have_childs) {
                   5076:                
                   5077:                /* write traling node information */
                   5078:                if (pretty_print) {
                   5079: #ifdef __AXL_OS_WIN32__
                   5080:                        memcpy (content + desp, "\r\n", 2);
                   5081:                        desp += 2;
                   5082: #else
                   5083:                        memcpy (content + desp, "\n", 1);
                   5084:                        desp += 1;
                   5085: #endif
                   5086:                } /* end if */
                   5087: 
                   5088:                /* dump content */
                   5089:                item = node->first;
                   5090:                desp = __axl_node_dump_items (item, content, level, pretty_print, desp, tabular);
                   5091:                
                   5092:                /* check for pretty print and tabular */
                   5093:                if (pretty_print) {
                   5094:                        desp += __axl_node_dump_at_write_indent (content + desp, tabular, level);
                   5095:                } /* end if */
                   5096: 
                   5097:        }else {
                   5098:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node is not empty and have no childs");
                   5099: 
                   5100:                /* dump content */
                   5101:                item = node->first;
                   5102:                desp = __axl_node_dump_items (item, content, level, pretty_print, desp, tabular);
                   5103:        } /* end if */
                   5104: 
                   5105:        /* dump close tag */
                   5106:        memcpy (content + desp, "</", 2);
                   5107:        desp += 2;
                   5108:        
                   5109:        memcpy (content + desp, node->name, strlen (node->name));
                   5110:        desp += strlen (node->name);
                   5111:        
                   5112:        memcpy (content + desp, ">", 1);
                   5113:        desp += 1;
                   5114: 
                   5115:        /* write traling node information */
                   5116:        if (pretty_print) {
                   5117: #ifdef __AXL_OS_WIN32__
                   5118:                memcpy (content + desp, "\r\n", 2);
                   5119:                desp += 2;
                   5120: #else
                   5121:                memcpy (content + desp, "\n", 1);
                   5122:                desp += 1;
                   5123: #endif
                   5124:        }
                   5125: 
                   5126:        /* return the result */
                   5127:        return desp;
                   5128: }
                   5129: 
                   5130: /**
                   5131:  * @internal Function used by axl_node_has_invalid_chars which also
                   5132:  * provides features for CDATA sections.
                   5133:  */
                   5134: axl_bool      axl_node_has_invalid_chars_internal        (const char * content,
                   5135:                                                          int          content_size,
                   5136:                                                          int        * added_size,
                   5137:                                                          axl_bool     cdata)
                   5138: {
                   5139:        int          iterator = 0;
                   5140:        axl_bool     result   = axl_false;
                   5141:        axl_return_val_if_fail (content, axl_false);
                   5142: 
                   5143:        /* reset additional size value */
                   5144:        if (added_size != NULL)
                   5145:                *added_size = 0;
                   5146: 
                   5147:        /* calculate the content size */
                   5148:        if (content_size == -1)
                   5149:                content_size = strlen (content);
                   5150: 
                   5151:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking valid sequence: content size=%d", content_size);
                   5152: 
                   5153:        /* iterate over all content defined */
                   5154:        while (iterator < content_size) {
                   5155:                /* check for &apos; */
                   5156:                if (content [iterator] == '\'') {
                   5157:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='\\'");
                   5158:                        result = axl_true;
                   5159:                        if (added_size != NULL)
                   5160:                                (*added_size) += 5;
                   5161:                }
                   5162: 
                   5163:                /* check for &quot; */
                   5164:                if (content [iterator] == '"') {
                   5165:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='\"'");
                   5166:                        result = axl_true;
                   5167:                        if (added_size != NULL)
                   5168:                                (*added_size) += 5;
                   5169:                }
                   5170: 
                   5171:                /* check for &amp; */
                   5172:                if (content [iterator] == '&') {
                   5173:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='&'");
                   5174:                        result = axl_true;
                   5175:                        if (added_size != NULL)
                   5176:                                (*added_size) += 4;
                   5177:                }
                   5178: 
                   5179:                /* check for &gt; */
                   5180:                if (content [iterator] == '>') {
                   5181:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='>'");
                   5182:                        result = axl_true;
                   5183:                        if (added_size != NULL)
                   5184:                                (*added_size) += 3;
                   5185:                }
                   5186: 
                   5187:                /* check for &lt; */
                   5188:                if (content [iterator] == '<') {
                   5189:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence='<'");
                   5190:                        result = axl_true;
                   5191:                        if (added_size != NULL)
                   5192:                                (*added_size) += 3;
                   5193:                }
                   5194: 
                   5195:                /* check for ]]> */
                   5196:                if (content [iterator] == ']' && content [iterator + 1] == ']' && content [iterator + 2] == '>') {
                   5197:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found invalid sequence=']]>'");
                   5198:                        result = axl_true;
                   5199:                        if (cdata) {
                   5200:                                /* inside CDATA section that is, we
                   5201:                                 * have to escape this value and
                   5202:                                 * reopen a new CDATA section to match
                   5203:                                 * with the last terminator */
                   5204:                                if (added_size != NULL)
                   5205:                                        (*added_size) += 15;
                   5206:                        } else {
                   5207:                                if (added_size != NULL)
                   5208:                                        (*added_size) += 3;
                   5209:                        }
                   5210:                        iterator += 3;
                   5211:                        continue;
                   5212:                } /* end if */
                   5213: 
                   5214:                /* update the iterator */
                   5215:                iterator++;
                   5216:        }
                   5217: 
                   5218:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "valid sequence checking result=%d: content size=%d, additional size=%d resul=%s", 
                   5219:                   result, content_size, (added_size != NULL) ? *added_size : 0, result ? "HAS INVALID SEQUENCES" : "HAS NO INVALID SEQUENCES");
                   5220: 
                   5221:        /* return results */
                   5222:        return result;
                   5223: }
                   5224: 
                   5225: /** 
                   5226:  * @brief Allows to check if the provided string have invalid chars
                   5227:  * that must be escaped by using the entity reference rather the value
                   5228:  * itself.
                   5229:  *
                   5230:  * This function is useful in the sense it allows to know if a
                   5231:  * particular content will contain elements not allowed by the XML 1.0
                   5232:  * definition to be placed directly (like &, <, ;, ' and ").
                   5233:  *
                   5234:  *
                   5235:  * This function use usually complemented with \ref axl_node_content_copy_and_escape. 
                   5236:  * 
                   5237:  * @param content The content to check.
                   5238:  *
                   5239:  * @param content_size The size of the content to be checked. If -1 is
                   5240:  * provided, the function will calculate the content length.
                   5241:  *
                   5242:  * @param added_size An integer reference where the additional size
                   5243:  * variable will be added. This additional size will be the space
                   5244:  * required to replace non-valid characters with entity
                   5245:  * references. This parameter is optional, so passing a NULL value is
                   5246:  * allowed.
                   5247:  * 
                   5248:  * @return \ref axl_true if the string contains non valid chars
                   5249:  * that must be escaped using entity references.
                   5250:  */
                   5251: axl_bool      axl_node_has_invalid_chars        (const char * content,
                   5252:                                                 int          content_size,
                   5253:                                                 int        * added_size)
                   5254: {
                   5255:        /* call to internal implementation supposing this is for a
                   5256:         * node without CDATA section */
                   5257:        return axl_node_has_invalid_chars_internal (content, content_size, added_size, axl_false);
                   5258: }
                   5259: 
                   5260: /** 
                   5261:  * @brief Allows to check if the provided string have escape sequences
                   5262:  * that must be defined by using the entity reference rather the value
                   5263:  * itself, taking into consideration the content will be used for a
                   5264:  * <![CDATA[..]]> section.
                   5265:  *
                   5266:  * This function is useful in the sense it allows to know if a
                   5267:  * particular content will contain elements not allowed by the XML 1.0
                   5268:  * definition to be placed directly (like &, <, ;, ' and ").
                   5269:  *
                   5270:  * This function use usually complemented with \ref axl_node_content_copy_and_escape_cdata. 
                   5271:  *
                   5272:  * @param content The content to check.
                   5273:  *
                   5274:  * @param content_size The size of the content to be checked. If -1 is
                   5275:  * provided, the function will calculate the content length.
                   5276:  *
                   5277:  * @param added_size An integer reference where the additional size
                   5278:  * variable will be added. This additional size will be the space
                   5279:  * required to replace non-valid characters with entity
                   5280:  * references. This parameter is optional, so passing a NULL value is
                   5281:  * allowed.
                   5282:  * 
                   5283:  * @return axl_true if the string contains non valid sequences that
                   5284:  * must be escaped using entity references.
                   5285:  */
                   5286: axl_bool      axl_node_has_invalid_chars_cdata        (const char * content,
                   5287:                                                       int          content_size,
                   5288:                                                       int        * added_size)
                   5289: {
                   5290:        /* call to internal implementation supposing this is for a
                   5291:         * node with CDATA section */
                   5292:        return axl_node_has_invalid_chars_internal (content, content_size, added_size, axl_true);
                   5293: }
                   5294: 
                   5295: /** 
                   5296:  * @brief Allows to perform a copy from the content provided, doing an
                   5297:  * xml character escaping for non allowed values (&, <, >, ' and ").
                   5298:  *
                   5299:  * This function must be used with \ref axl_node_has_invalid_chars to
                   5300:  * check if the content has escapable chars an to get the additional
                   5301:  * content that must be allocated by this function.
                   5302:  *
                   5303:  * Here is an example:
                   5304:  * \code
                   5305:  * char * content = "Some content with invalid chars & < >";
                   5306:  * int    additional_size;
                   5307:  * char * new_content
                   5308:  *
                   5309:  * if (axl_node_has_invalid_chars (content, strlen (content), &additional_size)) {
                   5310:  *      // found that the string has invalid chars, escape them
                   5311:  *      new_content = axl_node_content_copy_and_escape (content, strlen (content), additional_size);
                   5312:  * } 
                   5313:  *
                   5314:  * \endcode
                   5315:  * 
                   5316:  * @param content The content to be escaped. If this parameter is
                   5317:  * NULL, the function returns NULL.
                   5318:  * 
                   5319:  * @param content_size The content size for the first parameter.
                   5320:  *
                   5321:  * @param additional_size The additional size calculated from \ref axl_node_has_invalid_chars.
                   5322:  *
                   5323:  * @return A newly allocated string with all characters escaped. Use
                   5324:  * \ref axl_free to dealloc the result.
                   5325:  */
                   5326: char * axl_node_content_copy_and_escape (const char * content, 
                   5327:                                         int          content_size, 
                   5328:                                         int          additional_size)
                   5329: {
                   5330:        axl_return_val_if_fail (content, NULL);
                   5331:        
                   5332:        /* call to the internal implementation */
                   5333:        return __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_false);
                   5334: } 
                   5335: 
                   5336: /** 
                   5337:  * @brief Allows to perform a copy for the content provided, doing an
                   5338:  * xml character escaping for non allowed values (&, <, >, ' and ")
                   5339:  * taking into consideration the content will be placed inside a
                   5340:  * <![CDATA[..]]> declaration.
                   5341:  *
                   5342:  * This function must be used with \ref axl_node_has_invalid_chars_cdata to
                   5343:  * check if the content has escapable chars an to get the additional
                   5344:  * content that must be allocated by this function.
                   5345:  *
                   5346:  * Here is an example:
                   5347:  * \code
                   5348:  * char * content = "Some content with invalid chars & < >";
                   5349:  * int    additional_size;
                   5350:  * char * new_content
                   5351:  *
                   5352:  * if (axl_node_has_invalid_chars_cdata (content, strlen (content), &additional_size)) {
                   5353:  *      // found that the string has invalid chars, escape them
                   5354:  *      new_content = axl_node_content_copy_and_escape_cdata (content, strlen (content), additional_size);
                   5355:  * } 
                   5356:  * \endcode
                   5357:  * 
                   5358:  * @param content The content to be escaped. If this parameter is
                   5359:  * null, the function returns NULL.
                   5360:  * 
                   5361:  * @param content_size The content size for the first parameter.
                   5362:  *
                   5363:  * @param additional_size The additional size calculated from \ref axl_node_has_invalid_chars_cdata.
                   5364:  *
                   5365:  * @return A newly allocated string with all characters escaped. Use
                   5366:  * \ref axl_free to dealloc the result.
                   5367:  */
                   5368: char * axl_node_content_copy_and_escape_cdata (const char * content, 
                   5369:                                               int          content_size, 
                   5370:                                               int          additional_size)
                   5371: {
                   5372:        axl_return_val_if_fail (content, NULL);
                   5373:        
                   5374:        /* call to the internal implementation */
                   5375:        return __axl_node_content_copy_and_escape (content, content_size, additional_size, axl_true);
                   5376: } 
                   5377: 
                   5378: void __axl_node_free_internal (axlNode * node, axl_bool also_childs)
                   5379: {
                   5380:        axlItem * item;
                   5381:        axlItem * itemAux;
                   5382: 
                   5383:        axl_return_if_fail (node);
                   5384: 
                   5385:        /* free current node */
                   5386:        if (node->name != NULL && ! (node->conf & NODE_NAME_FROM_FACTORY))
                   5387:                axl_free (node->name);
                   5388: 
                   5389:        /* release memory hold by attributes */
                   5390:        if (node->attributes != NULL) {
                   5391:                if (node->attr_num <= 10)
                   5392:                        __axl_node_free_attr_list ((axlNodeAttr *) node->attributes);
                   5393:                else 
                   5394:                        axl_hash_free ((axlHash *) node->attributes);
                   5395:        }
                   5396: 
                   5397:        /* release memory hold by childs */
                   5398:        if (node->first != NULL && also_childs) {
                   5399:                /* get the first item */
                   5400:                item = node->first;
                   5401: 
                   5402:                /* foreach item stored */
                   5403:                while (item != NULL) {
                   5404: 
                   5405:                        /* get the next item */
                   5406:                        itemAux = item->next;                   
                   5407: 
                   5408:                        /* free the item */
                   5409:                        axl_item_free (item, axl_true);
                   5410:                        
                   5411:                        /* update reference */
                   5412:                        item = itemAux;
                   5413: 
                   5414:                } /* end while */
                   5415: 
                   5416:        } /* end if */
                   5417: 
                   5418:        /* free the item itself */
                   5419:        if (node->holder != NULL) {
                   5420:                if ((node->holder->type & ITEM_FROM_FACTORY) == 0) {
                   5421:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
                   5422:                                   "item holder found to be not from a factory, dealloc reference=0x%x, node=0x%x, type=%d",
                   5423:                                   node->holder, node, node->holder->type);
                   5424:                        axl_free (node->holder);
                   5425:                        node->holder = NULL;
                   5426:                }
                   5427:        }
                   5428: 
                   5429:        /* do not free the node itself */
                   5430:        return;
                   5431: }
                   5432: 
                   5433: /** 
                   5434:  * @brief Destroy the given node provided by the reference.
                   5435:  *
                   5436:  * The function will check for nodes that are NULL references,
                   5437:  * returning immediately.
                   5438:  * 
                   5439:  * @param node The node to destroy. 
                   5440:  */
                   5441: void axl_node_free (axlNode * node) 
                   5442: {
                   5443:        axlHash * hash;
                   5444:        axl_return_if_fail (node);
                   5445:        
                   5446:        /* get a reference to the hash */
                   5447:        hash = node->annotate_data;
                   5448: 
                   5449:        /* free internal content */
                   5450:        __axl_node_free_internal (node, axl_true);
                   5451: 
                   5452:        /* free attributes */
                   5453:        if (! (node->conf & NODE_FROM_FACTORY))
                   5454:                axl_free (node);
                   5455: 
                   5456:        /* annotate data deallocation must be done here because it is
                   5457:         * used by the application user and the library to store
                   5458:         * reference that could be pointing to internal structures
                   5459:         * deallocated by the __axl_node_free_internal */
                   5460:        axl_hash_free (hash);
                   5461: 
                   5462:        /* the node to release */
                   5463:        return;
                   5464: }
                   5465: 
                   5466: /** 
                   5467:  * @brief Allows to remove the provided node, optionally without
                   5468:  * removing childs inside it.
                   5469:  * 
                   5470:  * @param node The node to deallocate.
                   5471:  *
                   5472:  * @param also_childs Signal the function to also dealloc childs or
                   5473:  * not.
                   5474:  */
                   5475: void      axl_node_free_full       (axlNode * node, axl_bool also_childs)
                   5476: {
                   5477:        axlHash * hash;
                   5478:        axl_return_if_fail (node);
                   5479:        
                   5480:        /* get a reference to the hash */
                   5481:        hash = node->annotate_data;
                   5482: 
                   5483:        /* free node */
                   5484:        __axl_node_free_internal (node, axl_false);
                   5485: 
                   5486:        /* free the node itself */
                   5487:        if (!(node->conf & NODE_FROM_FACTORY))
                   5488:                axl_free (node);
                   5489: 
                   5490:        /* annotate data deallocation must be done here because it is
                   5491:         * used by the application user and the library to store
                   5492:         * reference that could be pointing to internal structures
                   5493:         * deallocated by the __axl_node_free_internal */
                   5494:        axl_hash_free (hash);
                   5495: 
                   5496:        return;
                   5497: }
                   5498: 
                   5499: /**
                   5500:  * @}
                   5501:  */
                   5502: 
                   5503: /** 
                   5504:  * \defgroup axl_node_attribute_cursor Axl Node Attribute iteration: An interface provided to iterate attribute nodes without knowing them.
                   5505:  */
                   5506: 
                   5507: /** 
                   5508:  * \addtogroup axl_node_attribute_cursor
                   5509:  * @{
                   5510:  */
                   5511: 
                   5512: 
                   5513: /** 
                   5514:  * @brief Allows to get a cursor to iterate attributes found in the
                   5515:  * provided node in a linear and efficient way.
                   5516:  *
                   5517:  * The \ref axlAttrCursor could be used to iterate attributes
                   5518:  * inside a particular node in an efficient way because it stores
                   5519:  * current state (position), hiding all module details, providing
                   5520:  * access to attributes without knowing them. Then using the following
                   5521:  * functions you can modify the state (current position to get):
                   5522:  * 
                   5523:  *   - \ref axl_node_attr_cursor_first
                   5524:  *   - \ref axl_node_attr_cursor_next
                   5525:  *
                   5526:  * Finally, the following functions are provided to get the key and
                   5527:  * the value data associated to the current selected attribute,
                   5528:  * pointed by the current status of the cursor:
                   5529:  * 
                   5530:  *   - \ref axl_node_attr_cursor_get_key (returns the key of the current attribute selected)
                   5531:  *   - \ref axl_node_attr_cursor_get_value (returns the value of the current attribute selected)
                   5532:  *
                   5533:  * Here is an example:
                   5534:  * \code
                   5535:  * axlPointer           key;
                   5536:  * axlPointer           value;
                   5537:  * axlAttrCursor * cursor;
                   5538:  * 
                   5539:  * // create the cursor 
                   5540:  * cursor   = axl_node_attr_cursor_new (node);
                   5541:  *
                   5542:  * // while there are more elements 
                   5543:  * while (axl_node_attr_cursor_has_item (cursor)) {
                   5544:  *
                   5545:  *   // get the value and key
                   5546:  *   key   = axl_node_attr_cursor_get_key   (cursor);
                   5547:  *   value = axl_node_attr_cursor_get_value (cursor);
                   5548:  *
                   5549:  *   // get the next 
                   5550:  *   axl_node_attr_cursor_next (cursor);
                   5551:  *
                   5552:  * } 
                   5553:  *
                   5554:  * // free the cursor 
                   5555:  * axl_node_attr_cursor_free (cursor);
                   5556:  * \endcode
                   5557:  *
                   5558:  * Once created the \ref axlAttrCursor you must release it and create
                   5559:  * a new one if you modify your \ref axlNode attribute configuration
                   5560:  * adding more items.
                   5561:  * 
                   5562:  * @param node The node that is requested to create the \ref
                   5563:  * axlAttrCursor reference to iterate all attributes inside.
                   5564:  * 
                   5565:  * @return A newly created \ref axlAttrCursor used to iterate
                   5566:  * attributes inside the node provided. Once finished you must call to
                   5567:  * \ref axl_node_attr_cursor_free.
                   5568:  */
                   5569: axlAttrCursor * axl_node_attr_cursor_new       (axlNode * node)
                   5570: {
                   5571:        axlAttrCursor * cursor;
                   5572: 
                   5573:        axl_return_val_if_fail (node, NULL);
                   5574: 
                   5575:        /* create and configure basics */
                   5576:        cursor        = axl_new (axlAttrCursor, 1);
                   5577:        cursor->node  = node;
                   5578:        cursor->count = node->attr_num;
                   5579: 
                   5580:        /* according to the number of attributes configure the hash or
                   5581:         * the linked attribte list */
                   5582:        if (cursor->count <= 10) {
                   5583:                /* just point to the first attribute (managed as AxlNodeAttr) */
                   5584:                cursor->data = node->attributes;                
                   5585:        } else {
                   5586:                /* create an axl hash cursor */
                   5587:                cursor->data = axl_hash_cursor_new ((axlHash *) node->attributes);
                   5588:        } /* end if */
                   5589: 
                   5590:        /* return created cursor */
                   5591:        return cursor;
                   5592: }
                   5593: 
                   5594: /** 
                   5595:  * @brief Allows to configure the provided cursor to point to the
                   5596:  * first attribute found inside the node.
                   5597:  * 
                   5598:  * @param cursor The cursor that is going to be configured.
                   5599:  */
                   5600: void                 axl_node_attr_cursor_first     (axlAttrCursor * cursor)
                   5601: {
                   5602:        axl_return_if_fail (cursor);
                   5603: 
                   5604:        /* check attribute configuration */
                   5605:        if (cursor->count != cursor->node->attr_num) {
                   5606:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5607:                return;
                   5608:        } /* end if */
                   5609: 
                   5610:        if (cursor->count <= 10) {
                   5611:                /* just point to the first attribute (managed as AxlAttribute) */
                   5612:                cursor->data = cursor->node->attributes;                
                   5613:        } else {
                   5614:                /* make hash cursor to point to the first */ 
                   5615:                axl_hash_cursor_first (cursor->data);
                   5616:        } /* end if */
                   5617:        
                   5618:        return;
                   5619: }
                   5620: 
                   5621: /** 
                   5622:  * @brief Configures the provided attribute cursor to point to the
                   5623:  * next attribute.
                   5624:  * 
                   5625:  * @param cursor The attribute cursor to be configured.
                   5626:  */
                   5627: void                 axl_node_attr_cursor_next      (axlAttrCursor * cursor)
                   5628: {
                   5629:        axl_return_if_fail (cursor);
                   5630: 
                   5631:        /* check attribute configuration */
                   5632:        if (cursor->count != cursor->node->attr_num) {
                   5633:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5634:                return;
                   5635:        } /* end if */
                   5636: 
                   5637:        if (cursor->count <= 10) {
                   5638:                /* check null values */
                   5639:                if (cursor->data == NULL)
                   5640:                        return;
                   5641: 
                   5642:                /* just point to the first attribute (managed as AxlAttribute) */
                   5643:                cursor->data = ((axlNodeAttr *) cursor->data)->next;
                   5644: 
                   5645:                return;
                   5646:        } /* end if */
                   5647: 
                   5648:        /* make hash cursor to point to the first */ 
                   5649:        axl_hash_cursor_next (cursor->data);
                   5650: 
                   5651:        
                   5652:        return;
                   5653: }
                   5654: 
                   5655: /** 
                   5656:  * @brief Allows to check if the is a next attribute, following
                   5657:  * current attribute selected.
                   5658:  * 
                   5659:  * @param cursor The cursor to be configured.
                   5660:  *
                   5661:  * @return \ref axl_true if it has next element, otherwise \ref axl_false.
                   5662:  */
                   5663: axl_bool                 axl_node_attr_cursor_has_next  (axlAttrCursor * cursor)
                   5664: {
                   5665:        axl_return_val_if_fail (cursor, axl_false);
                   5666: 
                   5667:        if (cursor->count != cursor->node->attr_num) {
                   5668:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5669:                return axl_false;
                   5670:        } /* end if */
                   5671: 
                   5672:        if (cursor->count <= 10) {
                   5673:                /* just point to the first attribute (managed as AxlAttribute) */
                   5674:                return (((axlNodeAttr *) cursor->data)->next) != NULL;
                   5675:        }  /* end if */
                   5676:        
                   5677:        /* make hash cursor to point to the first */ 
                   5678:        return axl_hash_cursor_has_next (cursor->data);
                   5679: }
                   5680: 
                   5681: /** 
                   5682:  * @brief Allows to check if the current position selected has an
                   5683:  * attribute reference.
                   5684:  * 
                   5685:  * @param cursor The cursor that is being queried.
                   5686:  *
                   5687:  * @return \ref axl_true if it has item element, otherwise \ref axl_false.
                   5688:  */
                   5689: axl_bool                 axl_node_attr_cursor_has_item  (axlAttrCursor * cursor)
                   5690: {
                   5691:        axl_return_val_if_fail (cursor, axl_false);
                   5692: 
                   5693:        /* check attribute configuration */
                   5694:        if (cursor->count != cursor->node->attr_num) {
                   5695:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5696:                return axl_false;
                   5697:        } /* end if */
                   5698: 
                   5699:        if (cursor->count <= 10) {
                   5700:                /* just point to the first attribute (managed as AxlAttribute) */
                   5701:                return cursor->data != NULL;
                   5702:        }  /* end if */
                   5703:        
                   5704:        /* make hash cursor to point to the first */ 
                   5705:        return axl_hash_cursor_has_item (cursor->data);
                   5706: }
                   5707: 
                   5708: /** 
                   5709:  * @brief Allows to get the attribute key associated to the current
                   5710:  * attribute selected by the cursor.
                   5711:  * 
                   5712:  * @param cursor The cursor that is being queried.
                   5713:  * 
                   5714:  * @return A reference to the attribute key or NULL if it fails.
                   5715:  */
                   5716: const char *         axl_node_attr_cursor_get_key   (axlAttrCursor * cursor)
                   5717: {
                   5718:        axl_return_val_if_fail (cursor, NULL);
                   5719: 
                   5720:        /* check attribute configuration */
                   5721:        if (cursor->count != cursor->node->attr_num) {
                   5722:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5723:                return NULL;
                   5724:        } /* end if */
                   5725: 
                   5726:        if (cursor->count <= 10) {
                   5727:                /* just point to the first attribute (managed as AxlAttribute) */
                   5728:                return ((axlNodeAttr *) cursor->data)->attribute;
                   5729:        }  /* end if */
                   5730:        
                   5731:        /* make hash cursor to point to the first */ 
                   5732:        return axl_hash_cursor_get_key (cursor->data);
                   5733: }
                   5734: 
                   5735: /** 
                   5736:  * @brief Allows to get the attribute value associated to the
                   5737:  * attribute selected by the cursor.
                   5738:  * 
                   5739:  * @param cursor The cursor that is being queried.
                   5740:  * 
                   5741:  * @return A reference to the attribute value or NULL if it fails.
                   5742:  */
                   5743: const char *         axl_node_attr_cursor_get_value (axlAttrCursor * cursor)
                   5744: {
                   5745:        axl_return_val_if_fail (cursor, NULL);
                   5746: 
                   5747:        /* check attribute configuration */
                   5748:        if (cursor->count != cursor->node->attr_num) {
                   5749:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "Your cursor was created with another attribute configuration, renew it.");
                   5750:                return NULL;
                   5751:        } /* end if */
                   5752: 
                   5753:        if (cursor->count <= 10) {
                   5754:                /* just point to the first attribute (managed as AxlAttribute) */
                   5755:                return ((axlNodeAttr *) cursor->data)->value;
                   5756:        }  /* end if */
                   5757:        
                   5758:        /* make hash cursor to point to the first */ 
                   5759:        return axl_hash_cursor_get_value (cursor->data);        
                   5760: }
                   5761: 
                   5762: /** 
                   5763:  * @brief Allows to release \ref axlAttrCursor.
                   5764:  * 
                   5765:  * @param cursor The cursor to release.
                   5766:  */
                   5767: void                 axl_node_attr_cursor_free      (axlAttrCursor * cursor)
                   5768: {
                   5769:        axl_return_if_fail (cursor);
                   5770: 
                   5771:        /* free hash cursor */
                   5772:        if (cursor->count > 10)
                   5773:                axl_hash_cursor_free (cursor->data);
                   5774: 
                   5775:        /* free the cursor */
                   5776:        axl_free (cursor);
                   5777: 
                   5778:        return;
                   5779: }
                   5780: 
                   5781: 
                   5782: /** 
                   5783:  * @internal Function that helps axl_node_attr_foreach to iterate all
                   5784:  * attributes.
                   5785:  */
                   5786: axl_bool __axl_node_attr_foreach_aux (axlPointer key, axlPointer data, axlPointer user_data, axlPointer user_data2, axlPointer user_data3)
                   5787: {
                   5788:        return ((axlNodeAttrForeachFunc) user_data) (key, data, user_data2, user_data3);
                   5789: }
                   5790: 
                   5791: /** 
                   5792:  * @brief Allows to provide a function which is called for each
                   5793:  * attribute installed on the provided node.
                   5794:  *
                   5795:  * This function will allow you to operate on every attribute
                   5796:  * installed, doing an foreach operation. This is an alternative API
                   5797:  * to the \ref axlAttrCursor, which could be used to save allocations.
                   5798:  * 
                   5799:  * @param node The node for which the provided function will be called
                   5800:  * for each attribute found.
                   5801:  *
                   5802:  * @param func The foreach function to be called.
                   5803:  *
                   5804:  * @param data User defined data to be passed to the foreach function.
                   5805:  *
                   5806:  * @param data2 Second user defined data to be passed to the foreach
                   5807:  * function.
                   5808:  */
                   5809: void            axl_node_attr_foreach          (axlNode       * node, 
                   5810:                                                axlNodeAttrForeachFunc func, 
                   5811:                                                axlPointer      data,
                   5812:                                                axlPointer      data2)
                   5813: {
                   5814:        axlNodeAttr * attr;
                   5815:        axl_return_if_fail (node);
                   5816:        axl_return_if_fail (func);
                   5817:        
                   5818:        /* if no attributes no foreach operation */
                   5819:        if (node->attributes == NULL)
                   5820:                return;
                   5821: 
                   5822:        /* store the attribute using the general case */
                   5823:        if (node->attr_num < 11) {
                   5824:                /* handled as a simple list */
                   5825:                attr = (axlNodeAttr *) node->attributes;
                   5826:                while (attr != NULL) {
                   5827:                        /* call to notify each attribute */
                   5828:                        if (func (attr->attribute, attr->value, data, data2))
                   5829:                                return;
                   5830: 
                   5831:                        /* get the next */
                   5832:                        attr = attr->next;
                   5833:                } /* end while */
                   5834:        } else {
                   5835:                /* handled as a hash */
                   5836:                axl_hash_foreach3 ((axlHash *) node->attributes, __axl_node_attr_foreach_aux, func, data, data2);
                   5837:        } /* end if */
                   5838: 
                   5839:        return;
                   5840: }
                   5841: 
                   5842: /**
                   5843:  * @}
                   5844:  */
                   5845: 
                   5846: /**
                   5847:  * \defgroup axl_item_module Axl Item: A basic item abstraction that represents a child node that could be another node, content, xml comment, etc.
                   5848:  */
                   5849: 
                   5850: /** 
                   5851:  * \addtogroup axl_item_module
                   5852:  * @{
                   5853:  */
                   5854: 
                   5855: /** 
                   5856:  * @brief Allows to create an \ref axlItem, with the provided type and
                   5857:  * holding the provided data.
                   5858:  *
                   5859:  * The function won't configure the parent node holding the
                   5860:  * item. There is an alternative API that allows to create an \ref
                   5861:  * axlItem without performing a copy: \ref axl_item_new_ref.
                   5862:  *
                   5863:  * @param type The type that will represent the \ref axlItem created.
                   5864:  *
                   5865:  * @param data Data associated to the axlItem. In the case the \ref
                   5866:  * axlItem being created will represent content (\ref ITEM_CONTENT),
                   5867:  * an entity ref (\ref ITEM_REF), a comment (\ref ITEM_COMMENT) or
                   5868:  * cdata (\ref ITEM_CDATA), the function will create a local copy. In
                   5869:  * the case of a \ref ITEM_NODE, the function will copy the entire
                   5870:  * node, and all its childs.
                   5871:  * 
                   5872:  * @return A newly allocated \ref axlItem with no parent and holding
                   5873:  * the data provided.
                   5874:  */
                   5875: axlItem     * axl_item_new             (AxlItemType type,
                   5876:                                        axlPointer  data)
                   5877: {
                   5878:        axlItem        * item = NULL;
                   5879:        axlNode        * node;
                   5880:        axlNodeContent * content;
                   5881: 
                   5882:        /* allocate an item type */
                   5883:        item         = axl_new (axlItem, 1);
                   5884:        item->type   = type;
                   5885: 
                   5886:        switch (axl_item_get_type (item)) {
                   5887:        case ITEM_NODE:
                   5888:                /* item the node */
                   5889:                node                 = axl_node_copy (item->data, axl_true, axl_true);
                   5890:                node->holder         = item;
                   5891:                item->data           = node;
                   5892:                break;
                   5893:        case ITEM_CONTENT:
                   5894:        case ITEM_CDATA:
                   5895:        case ITEM_COMMENT:
                   5896:                /* item content */
                   5897:                content               = axl_new (axlNodeContent, 1);
                   5898:                content->content      = axl_strdup ((const char *) data);
                   5899:                content->content_size = strlen ((const char *) data);
                   5900: 
                   5901:                /* item content */
                   5902:                item->data = content;
                   5903:                break;
                   5904:        case ITEM_PI:
                   5905:                /* item pi */
                   5906:                item->data = axl_pi_copy (data);
                   5907:                break;
                   5908:        case ITEM_REF:
                   5909:                /* not implemented yet */
                   5910:                break;
                   5911:        case ITEM_FROM_FACTORY:
                   5912:        case ITEM_CONTENT_FROM_FACTORY:
                   5913:                /* never reached */
                   5914:                break;
                   5915:        } /* end switch */
                   5916: 
                   5917:        /* return item created */
                   5918:        return item;
                   5919: }
                   5920: 
                   5921: /** 
                   5922:  * @brief Allows to create an \ref axlItem, with the provided type and
                   5923:  * holding the provided data.
                   5924:  *
                   5925:  * The function won't configure the parent node holding the item.
                   5926:  *
                   5927:  * @param type The type that will represent the \ref axlItem created.
                   5928:  *
                   5929:  * @param data Data associated to the axlItem. This function won't
                   5930:  * perform any copy for the data received. The user calling to this
                   5931:  * API must check that the data is only owned by the \ref axlItem
                   5932:  * created (that is, used by this function).
                   5933:  * 
                   5934:  * @return A newly allocated \ref axlItem with no parent and holding
                   5935:  * the data provided.
                   5936:  */
                   5937: axlItem     * axl_item_new_ref         (AxlItemType type,
                   5938:                                        axlPointer  data)
                   5939: {
                   5940:        axlItem        * item = NULL;
                   5941:        axlNode        * node;
                   5942:        axlNodeContent * content;
                   5943: 
                   5944:        /* allocate an item type */
                   5945:        item         = axl_new (axlItem, 1);
                   5946:        item->type   = type;
                   5947: 
                   5948:        switch (axl_item_get_type (item)) {
                   5949:        case ITEM_NODE:
                   5950:                /* item the node */
                   5951:                node = data;
                   5952:                node->holder         = item;
                   5953:                item->data           = node;
                   5954:                break;
                   5955:        case ITEM_CONTENT:
                   5956:        case ITEM_CDATA:
                   5957:        case ITEM_COMMENT:
                   5958:                /* item content */
                   5959:                content               = axl_new (axlNodeContent, 1);
                   5960:                content->content      = data;
                   5961:                content->content_size = strlen ((const char *) data);
                   5962: 
                   5963:                /* item content */
                   5964:                item->data = content;
                   5965:                break;
                   5966:        case ITEM_PI:
                   5967:                /* item pi */
                   5968:                item->data = data;
                   5969:                break;
                   5970:        case ITEM_REF:
                   5971:                /* not implemented yet */
                   5972:                break;
                   5973:        case ITEM_FROM_FACTORY:
                   5974:        case ITEM_CONTENT_FROM_FACTORY:
                   5975:                /* never reached */
                   5976:                break;
                   5977:        } /* end switch */
                   5978: 
                   5979:        /* return item created */
                   5980:        return item;
                   5981: }
                   5982: 
                   5983: 
                   5984: /** 
                   5985:  * @brief Allows to get the reference to the document that is holding
                   5986:  * the provided item without taking into consideration the item type.
                   5987:  * 
                   5988:  * @param item The item that is required to return its document.
                   5989:  * 
                   5990:  * @return A reference to the \ref axlDoc that is holding the item.
                   5991:  */
                   5992: axlDoc  * axl_item_get_doc         (axlItem * item)
                   5993: {
                   5994:        /* do not report an error since it is usual to have a node
                   5995:         * without an item hold configured: for example after
                   5996:         * axl_node_create */
                   5997:        if (item == NULL)
                   5998:                return NULL;
                   5999: 
                   6000:        /* return the document reference */
                   6001:        return item->doc;
                   6002: }
                   6003: 
                   6004: /** 
                   6005:  * @internal Internal function that allows to configure the document
                   6006:  * that is holding the item provided.
                   6007:  * 
                   6008:  * @param item The axlItem to be configured.
                   6009:  * @param doc The axlDoc reference to configure.
                   6010:  */
                   6011: void      axl_item_set_doc         (axlItem * item, axlDoc * doc)
                   6012: {
                   6013:        axl_return_if_fail (item);
                   6014: 
                   6015:        /* configure document */
                   6016:        item->doc = doc;
                   6017: 
                   6018:        return;
                   6019: }
                   6020: 
                   6021: /** 
                   6022:  * @brief Allows to get the parent that is containing the \ref axlItem
                   6023:  * provider. The parent of a \ref axlItem is always a node.
                   6024:  * 
                   6025:  * @param item The \ref axlItem reference that is required to return
                   6026:  * its parent.
                   6027:  * 
                   6028:  * @return A reference to the \ref axlNode.
                   6029:  */
                   6030: axlNode * axl_item_get_parent      (axlItem * item)
                   6031: {
                   6032:        /* return that we don't have parent */
                   6033:        if (item == NULL)
                   6034:                return NULL;
                   6035: 
                   6036:        /* return the parent */
                   6037:        return item->parent;
                   6038: }
                   6039: 
                   6040: /** 
                   6041:  * @brief Allows to get the following element that is next to the item
                   6042:  * reference provided (\ref axlItem), and at the same level.
                   6043:  * 
                   6044:  * @param item The item that is required to return its next reference.
                   6045:  * 
                   6046:  * @return A reference to the next element or NULL if it fails or no
                   6047:  * element is found next to the element provided.
                   6048:  */
                   6049: axlItem * axl_item_get_next        (axlItem * item)
                   6050: {
                   6051:        axl_return_val_if_fail (item, NULL);
                   6052: 
                   6053:        /* return the next element */
                   6054:        return item->next;
                   6055: }
                   6056: 
                   6057: /** 
                   6058:  * @brief Returns the following \ref axlItem to the \ref axlNode
                   6059:  * reference, in the same level.
                   6060:  * 
                   6061:  * @param node The node that is required to return the following item
                   6062:  * to it.
                   6063:  * 
                   6064:  * @return An reference to the following or NULL.
                   6065:  */
                   6066: axlItem * axl_item_node_next (axlNode * node)
                   6067: {
                   6068:        axl_return_val_if_fail (node, NULL);
                   6069: 
                   6070:        if (node->holder != NULL) {
                   6071:                /* return the next */
                   6072:                return node->holder->next;
                   6073:        }
                   6074: 
                   6075:        /* no holder, no next */
                   6076:        return NULL;
                   6077: 
                   6078: }
                   6079: 
                   6080: /** 
                   6081:  * @brief Allows to get the following element that is previous to the
                   6082:  * item reference provided (\ref axlItem), and at the same level.
                   6083:  * 
                   6084:  * @param item The item that is required to return its previous
                   6085:  * reference.
                   6086:  * 
                   6087:  * @return A reference to the previous element or NULL if it fails or
                   6088:  * no element is found previous to the element provided.
                   6089:  */
                   6090: axlItem * axl_item_get_previous        (axlItem * item)
                   6091: {
                   6092:        axl_return_val_if_fail (item, NULL);
                   6093: 
                   6094:        /* return the previous element */
                   6095:        return item->previous;
                   6096: }
                   6097: 
                   6098: /** 
                   6099:  * @brief Returns the previous \ref axlItem to the \ref axlNode
                   6100:  * reference, in the same level.
                   6101:  * 
                   6102:  * @param node The node that is required to return the previous item
                   6103:  * to it.
                   6104:  * 
                   6105:  * @return An reference to the previous or NULL.
                   6106:  */
                   6107: axlItem * axl_item_node_previous (axlNode * node)
                   6108: {
                   6109:        axl_return_val_if_fail (node, NULL);
                   6110: 
                   6111:        if (node->holder != NULL) {
                   6112:                /* return the previousx */
                   6113:                return node->holder->previous;
                   6114:        }
                   6115: 
                   6116:        /* no holder, no previous */
                   6117:        return NULL;
                   6118: }
                   6119: 
                   6120: /** 
                   6121:  * @brief Allows to get the \ref axlItem reference that is holding the
                   6122:  * node provided.
                   6123:  * 
                   6124:  * @param node The node that is required to return its holding item.
                   6125:  * 
                   6126:  * @return The item reference or NULL if it fails or it isn't set.
                   6127:  */
                   6128: axlItem     * axl_item_node_holder     (axlNode * node)
                   6129: {
                   6130:        axl_return_val_if_fail (node, NULL);
                   6131: 
                   6132:        /* return the holder */
                   6133:        return node->holder;
                   6134: }
                   6135: 
                   6136: /** 
                   6137:  * @brief Allows to get the very first child item stored on the
                   6138:  * provided \ref axlNode.
                   6139:  *
                   6140:  * This function is similar to \ref axl_node_get_first_child, but
                   6141:  * returning the first \ref axlItem no matter its type.
                   6142:  *
                   6143:  * This function is mainly used inside the MIXED API where nodes are
                   6144:  * expected to enclose content mixed with another xml nodes. See \ref
                   6145:  * axl_node_get_first_child for more details.
                   6146:  * 
                   6147:  * @param node The \ref axlNode reference that is required to return
                   6148:  * is first child reference (\ref axlItem).
                   6149:  * 
                   6150:  * @return The \ref axlItem reference or NULL if the axlNode is empty
                   6151:  * (\ref axl_node_is_empty) and have no childs (\ref
                   6152:  * axl_node_have_childs). The function also returns NULL if it fails
                   6153:  * (when it receives a NULL reference).
                   6154:  */
                   6155: axlItem     * axl_item_get_first_child (axlNode * node)
                   6156: {
                   6157:        /* check reference received */
                   6158:        axl_return_val_if_fail (node, NULL);
                   6159: 
                   6160:        /* return the first item reference */
                   6161:        return node->first;
                   6162: }
                   6163: 
                   6164: /** 
                   6165:  * @brief Allows to get the very last child item stored on the
                   6166:  * provided \ref axlNode.
                   6167:  *
                   6168:  * This function is similar to \ref axl_node_get_last_child, but
                   6169:  * returning the last \ref axlItem no matter its type.
                   6170:  *
                   6171:  * This function is mainly used inside the MIXED API where nodes are
                   6172:  * expected to enclose content mixed with another xml nodes. See \ref
                   6173:  * axl_node_get_last_child for more details.
                   6174:  * 
                   6175:  * @param node The \ref axlNode reference that is required to return
                   6176:  * is last child reference (\ref axlItem).
                   6177:  * 
                   6178:  * @return The \ref axlItem reference or NULL if the axlNode is empty
                   6179:  * (\ref axl_node_is_empty) and have no childs (\ref
                   6180:  * axl_node_have_childs). The function also returns NULL if it fails
                   6181:  * (when it receives a NULL reference).
                   6182:  */
                   6183: axlItem     * axl_item_get_last_child  (axlNode * node) 
                   6184: {
                   6185:        /* check reference received */
                   6186:        axl_return_val_if_fail (node, NULL);
                   6187: 
                   6188:        /* return the last item reference */
                   6189:        return node->last;
                   6190: }
                   6191: 
                   6192: /** 
                   6193:  * @brief Allows to get the item type that represents the reference
                   6194:  * received (\ref axlItem).
                   6195:  *
                   6196:  * Every \ref axlItem represents a particular content that could be
                   6197:  * found inside an xml document parsed by the library (\ref
                   6198:  * axlDoc). This function allows to return the type associated to the
                   6199:  * element encapsulated by the \ref axlItem. See \ref AxlItemType for
                   6200:  * more details.
                   6201:  * 
                   6202:  * @param item The reference that is required to return its type.
                   6203:  * 
                   6204:  * @return The type that is inside the reference or -1 if it fails.
                   6205:  */
                   6206: AxlItemType   axl_item_get_type        (axlItem * item)
                   6207: {
                   6208:        /* return stored type */
                   6209:        return item->type & (~ (ITEM_FROM_FACTORY | ITEM_CONTENT_FROM_FACTORY));
                   6210: }
                   6211: 
                   6212: /** 
                   6213:  * @brief Returns the item data that is stored inside the \ref axlItem
                   6214:  * received.
                   6215:  *
                   6216:  * According to the type that is representing the \ref axlItem
                   6217:  * received, it will return a particular type. Check \ref AxlItemType
                   6218:  * for more information.
                   6219:  *
                   6220:  * @param item The item that is required to return the data
                   6221:  * encapsulated on it.
                   6222:  * 
                   6223:  * @return A pointer to the data stored, or NULL if it fails. The
                   6224:  * pointer returned, in the case it is defined, mustn't be
                   6225:  * released. It is a internal reference to the content.
                   6226:  */
                   6227: axlPointer axl_item_get_data (axlItem * item)
                   6228: {
                   6229:        axl_return_val_if_fail (item, NULL);
                   6230: 
                   6231:        /* return stored type */
                   6232:        return item->data;
                   6233: }
                   6234: 
                   6235: /** 
                   6236:  * @brief Convenience API that allows to get the content stored (and
                   6237:  * its size) from the received \ref axlItem, supposing it is storing
                   6238:  * an \ref ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref ITEM_REF.
                   6239:  *
                   6240:  * @param item The \ref axlItem that is supposed to store an item with
                   6241:  * type: \ref ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref
                   6242:  * ITEM_REF.
                   6243:  *
                   6244:  * @param size Optional variable reference. If defined, if returns the
                   6245:  * content size.
                   6246:  * 
                   6247:  * @return An internal reference to the content stored and optionally
                   6248:  * the content size notified on the variable received. In the case the
                   6249:  * function receives an incompatible \ref axlItem (which is not \ref
                   6250:  * ITEM_CONTENT, \ref ITEM_CDATA, \ref ITEM_COMMENT or \ref ITEM_REF),
                   6251:  * the function will return NULL, and the optional variable will be
                   6252:  * filled with -1.
                   6253:  */
                   6254: char        * axl_item_get_content     (axlItem * item, 
                   6255:                                        int     * size)
                   6256: {
                   6257:        axlNodeContent * content;
                   6258: 
                   6259:        /* check content received */
                   6260:        if (size != NULL)
                   6261:                *size = -1;
                   6262:        
                   6263:        /* check if the item reference is NULL */
                   6264:        axl_return_val_if_fail (item, 
                   6265:                                NULL);
                   6266:        axl_return_val_if_fail (axl_item_get_type (item) != ITEM_NODE && axl_item_get_type (item) != ITEM_PI, 
                   6267:                                NULL);
                   6268: 
                   6269:        /* get the content */
                   6270:        content = item->data;
                   6271: 
                   6272:        /* fill the size */
                   6273:        if (size != NULL)
                   6274:                *size = content->content_size;
                   6275: 
                   6276:        /* return a pointer to the content */
                   6277:        return content->content;
                   6278: }
                   6279: 
                   6280: /* prepare the item to be added to the xml document */
                   6281: axlItem *  __axl_item_common_configure (axlNode * parent, AxlItemType type, axlPointer data)
                   6282: {
                   6283:        axlNode * node = NULL;
                   6284:        axlItem * item = NULL;
                   6285: 
                   6286:        /* return if the parent is defined */
                   6287:        axl_return_val_if_fail (parent, NULL);
                   6288: 
                   6289:        /* check if the node received already have a pointer to a
                   6290:         * holder created */
                   6291:        if (type & ITEM_NODE) {
                   6292:                /* get a reference to the node */
                   6293:                node = (axlNode *) data;
                   6294: 
                   6295:                /* get a reference to the holder */
                   6296:                item = node->holder;
                   6297: 
                   6298:                /* check if the current item was allocated from a
                   6299:                 * factory to ensure we don't loose that
                   6300:                 * information */
                   6301:                if ((item != NULL) && (item->type & ITEM_FROM_FACTORY)) 
                   6302:                        type = type | ITEM_FROM_FACTORY;
                   6303:        }
                   6304: 
                   6305:        /* create an item to hold the child, configuring the node, the
                   6306:         * parent and the document */
                   6307:        if (item == NULL) {
                   6308:                if ((parent->holder != NULL) && (parent->holder->doc != NULL)) {
                   6309:                        item = axl_item_factory_get (axl_doc_get_item_factory (parent->holder->doc));
                   6310:                        type = type | ITEM_FROM_FACTORY; 
                   6311:                } else 
                   6312:                        item   = axl_new (axlItem, 1);
                   6313:        }
                   6314:        item->type     = type;
                   6315:        item->data     = data;
                   6316:        item->doc      = (parent->holder != NULL) ? parent->holder->doc : NULL;
                   6317: 
                   6318:        if (item->type & ITEM_NODE) {
                   6319:                /* now configure the item that will hold the new child */
                   6320:                node->holder  = item;
                   6321:        } /* end if */  
                   6322:        
                   6323:        /* return item created */
                   6324:        return item;
                   6325: }
                   6326: 
                   6327: /** 
                   6328:  * @internal Function that helps adding a new item to the provided
                   6329:  * parent node.
                   6330:  *
                   6331:  * The new item will be added as flaged by the type provided. The
                   6332:  * function isn't exposed to the public API because there are better
                   6333:  * alternatives to add items to a \ref axlNode. Don't use this API
                   6334:  * directly.
                   6335:  * 
                   6336:  * @param parent The axl node that will receive the new content.
                   6337:  *
                   6338:  * @param type The type to configure to the new item.
                   6339:  *
                   6340:  * @param data The data associated to the data being stored.
                   6341:  *
                   6342:  * NOTE: the function doesn't check data received as it is supposed to
                   6343:  * receive calls from the library.
                   6344:  */
                   6345: void axl_item_set_child (axlNode * parent, AxlItemType type, axlPointer data)
                   6346: {
                   6347:        axlItem * item;
                   6348: 
                   6349:        /* prepare the item to be added to the xml document */
                   6350:        item = __axl_item_common_configure (parent, type, data);
                   6351: 
                   6352:        /* call to set child with a created item */
                   6353:        axl_item_set_child_ref (parent, item);
                   6354: 
                   6355:        return;
                   6356: }
                   6357: 
                   6358: /** 
                   6359:  * @brief Allows to configure xml content just after the item used as
                   6360:  * reference.
                   6361:  *
                   6362:  * @param item The item used as reference to place the content after
                   6363:  * it.
                   6364:  *
                   6365:  * @param type AxlItemType to configure the content to be placed.
                   6366:  *
                   6367:  * @param data Pointer that is associated to the type.
                   6368:  */
                   6369: void          axl_item_set_after       (axlItem * item,
                   6370:                                        AxlItemType type,
                   6371:                                        axlPointer data)
                   6372: {
                   6373:        axlItem * new_item = NULL;
                   6374: 
                   6375:        /* prepare the item to be added to the xml document */
                   6376:        new_item = __axl_item_common_configure (item->parent, type, data);
                   6377: 
                   6378:        /* configure the parent node */
                   6379:        new_item->parent   = item->parent;
                   6380: 
                   6381:        /* configure new item references */
                   6382:        new_item->previous = item;
                   6383:        new_item->next     = item->next;
                   6384:        
                   6385:        /* configure item references */
                   6386:        if (item->next != NULL)
                   6387:                item->next->previous = new_item;
                   6388:        else
                   6389:                item->parent->last  = new_item;
                   6390:        item->next = new_item;
                   6391: 
                   6392:        return;
                   6393: }
                   6394: 
                   6395: /* call to set child with a created item */
                   6396: void axl_item_set_child_ref (axlNode * parent, axlItem * item)
                   6397: {
                   6398:        axl_return_if_fail (parent);
                   6399:        axl_return_if_fail (item);
                   6400: 
                   6401:        /* configure the parent node */
                   6402:        item->parent   = parent;
                   6403: 
                   6404:        /* get the current last child */
                   6405:        if (parent->first == NULL) {
                   6406:                /* init first and last reference to the only one
                   6407:                 * child */
                   6408:                parent->first = item;
                   6409:                parent->last  = item;
                   6410:        }else {
                   6411:                /* configure the next item to the current last
                   6412:                 * child */
                   6413:                parent->last->next = item;
                   6414: 
                   6415:                /* update the last child reference */
                   6416:                item->previous    = parent->last;
                   6417:                item->next        = NULL;
                   6418:                parent->last      = item;
                   6419:        }
                   6420: 
                   6421:        return;
                   6422: }
                   6423: 
                   6424: /** 
                   6425:  * @brief Copy the reference provided creating a newly allocated
                   6426:  * reference, including the content inside.
                   6427:  * 
                   6428:  * @param item The item to copy.
                   6429:  *
                   6430:  * @param set_parent Optionally, allows to provide the parent to be
                   6431:  * configured to the item created. This is really required while
                   6432:  * copying items that contains nodes.
                   6433:  * 
                   6434:  * @return A newly allocated \ref axlItem reference, containing the
                   6435:  * same data (a deep copy) and optionally configured with the provided
                   6436:  * parent.
                   6437:  */
                   6438: axlItem * axl_item_copy (axlItem * item, axlNode * set_parent)
                   6439: {
                   6440:        axlItem        * copy;
                   6441:        axlNode        * node;
                   6442:        axlNodeContent * content;
                   6443: 
                   6444:        /* check values received */
                   6445:        axl_return_val_if_fail (item, NULL);
                   6446: 
                   6447:        /* allocate an copy type */
                   6448:        copy         = axl_new (axlItem, 1);
                   6449:        copy->type   = axl_item_get_type (item);
                   6450:        copy->parent = set_parent;
                   6451: 
                   6452:        switch (axl_item_get_type (item)) {
                   6453:        case ITEM_NODE:
                   6454:                /* copy the node */
                   6455:                node                 = axl_node_copy (item->data, axl_true, axl_true);
                   6456:                node->holder         = copy;
                   6457:                copy->data           = node;
                   6458:                break;
                   6459:        case ITEM_CONTENT:
                   6460:        case ITEM_CDATA:
                   6461:        case ITEM_COMMENT:
                   6462:                /* copy content */
                   6463:                content               = axl_new (axlNodeContent, 1);
                   6464:                content->content      = axl_strdup (((axlNodeContent * ) item->data)->content);
                   6465:                content->content_size = ((axlNodeContent * ) item->data)->content_size;
                   6466: 
                   6467:                /* copy content */
                   6468:                copy->data = content;
                   6469:                break;
                   6470:        case ITEM_PI:
                   6471:                /* copy pi */
                   6472:                copy->data = axl_pi_copy (item->data);
                   6473:                break;
                   6474:        case ITEM_REF:
                   6475:                /* not implemented yet */
                   6476:                break;
                   6477:        case ITEM_FROM_FACTORY:
                   6478:        case ITEM_CONTENT_FROM_FACTORY:
                   6479:                /* never reached */
                   6480:                break;
                   6481:        } /* end switch */
                   6482: 
                   6483:        /* return copy created */
                   6484:        return copy;
                   6485: }
                   6486: 
                   6487: /** 
                   6488:  * @brief Allows to remove the \ref axlItem instance from the document
                   6489:  * that is currently holding it, optionally deallocating the memory
                   6490:  * used by the structure.
                   6491:  * 
                   6492:  * @param item The item to remove from its container (without taking
                   6493:  * into consideration the item type).
                   6494:  *
                   6495:  * @param dealloc Deallocs the memory used by the \ref axlItem
                   6496:  * reference.
                   6497:  */
                   6498: void          axl_item_remove          (axlItem   * item,
                   6499:                                        axl_bool    dealloc)
                   6500: {
                   6501: 
                   6502:        /* free the item */
                   6503:        axl_return_if_fail (item);
                   6504: 
                   6505:        /* realloc references */
                   6506:        if (item->previous != NULL)
                   6507:                item->previous->next = item->next;
                   6508: 
                   6509:        if (item->next != NULL)
                   6510:                item->next->previous = item->previous;
                   6511: 
                   6512:        /* realloc parent references in the case of a node */
                   6513:        if (axl_item_get_type (item) == ITEM_NODE) {
                   6514:                if (item->previous == NULL)
                   6515:                        item->parent->first = item->next;
                   6516: 
                   6517:                if (item->next == NULL)
                   6518:                        item->parent->last  = item->previous;
                   6519:        } /* end if */
                   6520:        
                   6521:        /* free the item */
                   6522:        item->next     = NULL;
                   6523:        item->previous = NULL;
                   6524: 
                   6525:        if (dealloc) {
                   6526:                axl_item_free (item, axl_true);
                   6527:        } /* end if */
                   6528: 
                   6529:        return;
                   6530: 
                   6531: } /* end axl_item_remove */
                   6532: 
                   6533: /** 
                   6534:  * @brief Allows to replace the content held by the \ref axlItem
                   6535:  * reference with a new \ref axlItem, updating all references, and
                   6536:  * optionally, deallocating the memory used by the previous item
                   6537:  * reference.
                   6538:  * 
                   6539:  * @param item The item to be replaced.
                   6540:  *
                   6541:  * @param new_item The new item to be placed where the previous one is
                   6542:  * located.
                   6543:  *
                   6544:  * @param dealloc Signal to function to dealloc the memory hold the
                   6545:  * the item replaced.
                   6546:  */
                   6547: void          axl_item_replace        (axlItem  * item, 
                   6548:                                       axlItem  * new_item,
                   6549:                                       axl_bool   dealloc)
                   6550: {
                   6551:        /* free the item */
                   6552:        axl_return_if_fail (item);
                   6553:        axl_return_if_fail (new_item);
                   6554: 
                   6555:        /* realloc references */
                   6556:        if (item->previous != NULL) {
                   6557:                item->previous->next = new_item;
                   6558:                new_item->previous   = item->previous;
                   6559:        }
                   6560: 
                   6561:        if (item->next != NULL) {
                   6562:                item->next->previous = new_item;
                   6563:                new_item->next       = item->next;
                   6564:        }
                   6565: 
                   6566:        /* realloc parent references in the case of a node */
                   6567:        if (axl_item_get_type (item) == ITEM_NODE) {
                   6568:                if (item->previous == NULL)
                   6569:                        item->parent->first = new_item;
                   6570: 
                   6571:                if (item->next == NULL)
                   6572:                        item->parent->last = new_item;
                   6573:        } /* end if */
                   6574: 
                   6575:        /* free the item */
                   6576:        item->next     = NULL;
                   6577:        item->previous = NULL;
                   6578: 
                   6579:        /* configure values */
                   6580:        new_item->parent = item->parent;
                   6581:        new_item->doc    = item->doc;
                   6582: 
                   6583:        if (dealloc) {
                   6584:                axl_item_free (item, axl_true);
                   6585: 
                   6586:        } /* end if */
                   6587: 
                   6588:        return;
                   6589: 
                   6590: } /* end axl_item_replace */
                   6591: 
                   6592: /** 
                   6593:  * @brief Allows to transfer all childs contained inside the provided
                   6594:  * \ref axlNode (old_parent) placed after the provided axlItem
                   6595:  * (item_ref) on the same level.
                   6596:  *
                   6597:  * This function allows to manipulate a xml document loaded inside
                   6598:  * memory, by transfering all childs (including xml nodes, xml
                   6599:  * comments, content, process instructions and entity references) from
                   6600:  * the selected parent (the old parent) provided by the
                   6601:  * <i>old_parent</i> attribute, to be placed at the same level, where
                   6602:  * the <i>item_ref</i> is situated following it.
                   6603:  *
                   6604:  * 
                   6605:  * @param old_parent Previous parent, where the childs to be
                   6606:  * transfered will be found.
                   6607:  *
                   6608:  * @param item_ref The \ref axlItem that will act as a reference
                   6609:  * placing all childs following the item.
                   6610:  */
                   6611: void          axl_item_transfer_childs_after (axlNode * old_parent,
                   6612:                                              axlItem * item_ref)
                   6613: {
                   6614:        axlItem * item;
                   6615:        axlItem * item_aux;
                   6616: 
                   6617:        /* get the first child for the old parent */
                   6618:        item = old_parent->first;
                   6619: 
                   6620:        /* check if the parent node contains childs to be
                   6621:         * transferred. If no child is found, just return */
                   6622:        if (item == NULL)
                   6623:                return;
                   6624: 
                   6625:        /* remember previous next */
                   6626:        item_aux       = item_ref->next;
                   6627:        
                   6628:        /* make the first child to follow the item ref */
                   6629:        item_ref->next = item;
                   6630:        item->previous = item_ref;
                   6631: 
                   6632:        /* set the next at the end of all items transferred, and the
                   6633:         * new parent node */
                   6634:        while (item != NULL) {
                   6635:                /* configure the new parent */
                   6636:                item->parent = item_ref->parent;
                   6637: 
                   6638:                /* check the item to be the last */
                   6639:                if (item->next == NULL) {
                   6640:                        /* the last item was found, configure it */
                   6641:                        item->next = item_aux;
                   6642: 
                   6643:                        /* configure it to point to the last item
                   6644:                         * transferred */
                   6645:                        if (item_aux != NULL)
                   6646:                                item_aux->previous = item;
                   6647: 
                   6648:                        /* break the loop! */
                   6649:                        break;
                   6650:                } /* end if */
                   6651: 
                   6652:                /* get the next */
                   6653:                item = item->next;
                   6654:                
                   6655:        } /* end while */
                   6656: 
                   6657:        /* check that the item selected to be reference isn't the last
                   6658:         * child inside new parent node. If it is, update the new
                   6659:         * last */
                   6660:        if (item_aux == NULL) {
                   6661:                /* because item is pointing to the last item in the
                   6662:                 * level, use it as the new last */
                   6663:                item->parent->last = item;
                   6664:        } /* end if */
                   6665: 
                   6666:        /* clear reference from previous parent */
                   6667:        old_parent->first     = NULL;
                   6668:        old_parent->last      = NULL;
                   6669: 
                   6670:        return;
                   6671: }
                   6672: 
                   6673: /** 
                   6674:  * @brief Allows to check if both items are equal, considering the
                   6675:  * item type and the content associated to the item type.
                   6676:  *
                   6677:  * @param item The first item to check.
                   6678:  *
                   6679:  * @param item2 The second item to check.
                   6680:  * 
                   6681:  * @param trimmed This paramenter allows to configure how the equal
                   6682:  * check is performed for content element (\ref ITEM_CONTENT, \ref
                   6683:  * ITEM_CDATA, \ref ITEM_COMMENT and \ref ITEM_REF).
                   6684:  *
                   6685:  * @param error Optional \ref axlError reference where textual
                   6686:  * diagnostic is reported.
                   6687:  *
                   6688:  *
                   6689:  * @return \ref axl_true if the both items represents the same
                   6690:  * information, otherwise \ref axl_false is returned. If the function
                   6691:  * receives a null value it will return axl_false.
                   6692:  */
                   6693: axl_bool          axl_item_are_equal_full      (axlItem    * item,
                   6694:                                                axlItem    * item2,
                   6695:                                                axl_bool     trimmed,
                   6696:                                                axlError  ** error)
                   6697: {
                   6698:        axlNodeContent * content;
                   6699:        axlNodeContent * content2;
                   6700: 
                   6701:        /* trim content */
                   6702:        char           * trim;
                   6703:        char           * trim2;
                   6704:        axl_bool         result;
                   6705:        
                   6706:        axl_return_val_if_fail (item, axl_false);
                   6707:        axl_return_val_if_fail (item2, axl_false);
                   6708: 
                   6709:        /* basic type check */
                   6710:        if (axl_item_get_type (item) != axl_item_get_type (item2)) {
                   6711:                axl_error_report (error, -1, "Items types differs (%d != %d)", 
                   6712:                                  axl_item_get_type (item), axl_item_get_type (item2));
                   6713:                return axl_false;
                   6714:        }
                   6715: 
                   6716:        /* according the type */
                   6717:        switch (axl_item_get_type (item)) {
                   6718:        case ITEM_NODE:
                   6719:                /* check that both nodes are equal */
                   6720:                return axl_node_are_equal_full (item->data, item2->data, error);
                   6721:        case ITEM_CONTENT:
                   6722:        case ITEM_CDATA:
                   6723:        case ITEM_COMMENT:
                   6724:        case ITEM_REF:
                   6725:                /* get the contenet */
                   6726:                content  = item->data;
                   6727:                content2 = item2->data;
                   6728: 
                   6729:                if (! trimmed) {
                   6730:                        /* check first content length */
                   6731:                        if (content->content_size != content2->content_size) {
                   6732:                                axl_error_report (error, -1, "Items content size differs (%s:%d != %s:%d)", 
                   6733:                                                  content->content, 
                   6734:                                                  content->content_size, 
                   6735:                                                  content2->content,
                   6736:                                                  content2->content_size);
                   6737:                                return axl_false;
                   6738:                        }
                   6739:                        
                   6740:                        /* now check content value */
                   6741:                        return axl_cmp (content->content, content2->content);
                   6742:                }else {
                   6743:                        /* duplicate the content */
                   6744:                        trim = axl_strdup (content->content);
                   6745:                        trim2 = axl_strdup (content2->content);
                   6746: 
                   6747:                        /* trim content */
                   6748:                        axl_stream_trim (trim);
                   6749:                        axl_stream_trim (trim2);
                   6750: 
                   6751:                        /* do the comparision */
                   6752:                        result = axl_cmp (trim, trim2);
                   6753: 
                   6754:                        if (! result) {
                   6755:                                axl_error_report (error, -1, "Trimmed content differs ('%s' != '%s')", trim, trim2);
                   6756:                        } /* end if */
                   6757: 
                   6758:                        /* free data */
                   6759:                        axl_free (trim);
                   6760:                        axl_free (trim2);
                   6761:                        
                   6762:                        return result;
                   6763: 
                   6764:                }
                   6765:        case ITEM_PI:
                   6766:                /* pi case */
                   6767:                return axl_pi_are_equal (item->data, item2->data);
                   6768:        default:
                   6769:                /* no case identified, not equal */
                   6770:                break;
                   6771:        } /* end switch */
                   6772:        
                   6773:        axl_error_report (error, -1, "Item type not found, unable to check");
                   6774:        return axl_false;
                   6775: }
                   6776: 
                   6777: /** 
                   6778:  * @brief Allows to check if both items are equal, considering the
                   6779:  * item type and the content associated to the item type.
                   6780:  *
                   6781:  *
                   6782:  * @param item The first item to check.  
                   6783:  *
                   6784:  * @param item2 The second item to check.
                   6785:  *
                   6786:  * @param trimmed This paramenter allows to configure how equal
                   6787:  * checking is performed for content element (\ref ITEM_CONTENT, \ref
                   6788:  * ITEM_CDATA, \ref ITEM_COMMENT and \ref ITEM_REF).
                   6789:  *
                   6790:  * @return \ref axl_true if the both items represents the same
                   6791:  * information, otherwise \ref axl_false is returned. If the function
                   6792:  * receives a null value it will return axl_false.
                   6793:  */
                   6794: axl_bool          axl_item_are_equal      (axlItem   * item,
                   6795:                                           axlItem   * item2,
                   6796:                                           axl_bool    trimmed)
                   6797: {
                   6798:        /* call to check if both items are equal */
                   6799:        return axl_item_are_equal_full (item, item2, trimmed, NULL);
                   6800: }
                   6801: 
                   6802: /** 
                   6803:  * @brief Allows to release the memory hold the item reference
                   6804:  * provided, and the value stored inside it.
                   6805:  * 
                   6806:  * @param item The item to dealloc.
                   6807:  *
                   6808:  * @param dealloc \ref axl_true to also dealloc the value inside.
                   6809:  */
                   6810: void          axl_item_free           (axlItem  * item,
                   6811:                                       axl_bool   dealloc)
                   6812: {
                   6813:        axl_return_if_fail (item);
                   6814: 
                   6815:        
                   6816:        /* according the type */
                   6817:        switch (axl_item_get_type (item)) {
                   6818:        case ITEM_NODE:
                   6819:                /* free the node */
                   6820:                axl_node_free (item->data);
                   6821:                break;
                   6822:        case ITEM_CONTENT:
                   6823:        case ITEM_CDATA:
                   6824:        case ITEM_COMMENT:
                   6825:        case ITEM_REF:
                   6826:                /* all of them, managed equally */
                   6827: 
                   6828:                /* check and free content */
                   6829:                if ((item->type & ITEM_CONTENT_FROM_FACTORY) == 0) {
                   6830:                        axl_free (((axlNodeContent *)item->data)->content);
                   6831: 
                   6832:                        /* free node */
                   6833:                        axl_free ((axlNodeContent *)item->data);
                   6834:                }
                   6835:                
                   6836:                if ((item->type & ITEM_FROM_FACTORY) == 0)
                   6837:                        axl_free (item);
                   6838:                break;
                   6839:        case ITEM_PI:
                   6840:                /* an process instruction */
                   6841:                axl_pi_free (item->data);
                   6842:                
                   6843:                /* free the item */
                   6844:                if ((item->type & ITEM_FROM_FACTORY) == 0)
                   6845:                        axl_free (item);
                   6846:                break;
                   6847:        case ITEM_FROM_FACTORY:
                   6848:        case ITEM_CONTENT_FROM_FACTORY:
                   6849:                /* never reached */
                   6850:                break;
                   6851:                
                   6852:        } /* end switch */
                   6853: 
                   6854: 
                   6855:        return;
                   6856: }
                   6857: 
                   6858: axlFactory * axl_item_factory_create (void)
                   6859: {
                   6860:        return axl_factory_create (sizeof (axlItem));
                   6861: }
                   6862: 
                   6863: axlItem        * axl_item_factory_get (axlFactory * factory)
                   6864: {
                   6865:        return axl_factory_get (factory);
                   6866: }
                   6867: 
                   6868: axlFactory * axl_node_factory_create (void)
                   6869: {
                   6870:        return axl_factory_create (sizeof (axlNode));
                   6871: }
                   6872: 
                   6873: axlNode    * axl_node_factory_get (axlFactory * factory)
                   6874: {
                   6875:        /* get a node */
                   6876:        axlNode * node = axl_factory_get (factory);
                   6877:        
                   6878:        /* configure it */
                   6879:        node->conf = NODE_FROM_FACTORY;
                   6880: 
                   6881:        return node;
                   6882: }
                   6883: 
                   6884: axlFactory     * axl_item_content_factory_create (void)
                   6885: {
                   6886:        /* create a factory for axlNodeContent elements */
                   6887:        return axl_factory_create (sizeof (axlNodeContent));
                   6888: }
                   6889: 
                   6890: axlFactory     * axl_item_attr_factory_create (void)
                   6891: {
                   6892:        /* create a factory for axlNodeAttr elements */
                   6893:        return axl_factory_create (sizeof (axlNodeAttr));
                   6894: }
                   6895: 
                   6896: /* @} */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>