Annotation of gpl/axl/src/axl_doc.c, revision 1.1.1.1

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: /**
                     41:  * @internal
                     42:  * @brief XML 1.0 Third edition grammar
                     43:  *
                     44:  * [1]  document       ::=   prolog element Misc*
                     45:  * [1]  status: partially
                     46:  *
                     47:  * [2]  Char           ::=   \x9 | \xA | \xD | \x20-\xD7FF | \xE000-\xFFFD | \x10000-\10FFFF
                     48:  * [2]  status: not implemented 
                     49:  *
                     50:  * [3]  S              ::= ( \x20 | \x9 | \xD | \xA)
                     51:  * [3]  status: ok
                     52:  *
                     53:  * [4]  NameChar       ::=   Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
                     54:  * [4]  status: not implemented
                     55:  *
                     56:  * [5]  Name           ::= ( Letter | '_' | ':' |) ( NameChar )*
                     57:  * [5]  status: not implemented
                     58:  *
                     59:  * [6]  Names          ::=   Name ( \x20 Name )*
                     60:  * [6]  status: not implemented
                     61:  *
                     62:  * [7]  Nmtoken        ::= ( NameChar ) +
                     63:  * [7]  status: not implemented
                     64:  *
                     65:  * [8]  Nmtokens       ::=   Nmtoken (\x20 Nmtoken)*
                     66:  * [8]  status: not implemented
                     67:  *
                     68:  * [9]  EntityValue    ::=   '"' ( [^%&"] | PEReference | Reference )* '"' | "'" ( [^%&'] ! PEReference | Reference )* "'"
                     69:  * [9]  status: not implemented
                     70:  *
                     71:  * [10] AttValue       ::=   '"' ( [^<&"] | Reference)*  '"' | "'" ( [^<&'] | Reference )* "'"
                     72:  * [10]  status: not implemented
                     73:  *
                     74:  * [11] SystemLiteral  ::= ( '"' [^"]* '"') | ("'" [^']* "'")
                     75:  * [11]  status: not implemented
                     76:  *
                     77:  * [12] PubidLiteral   ::=   '"' PubidChar* '"' | "'" (PubidChar - "'") * "'"
                     78:  * [12]  status: not implemented
                     79:  *
                     80:  * [13] PubidChar      ::=   \x20 | \xD | \xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
                     81:  * [13]  status: not implemented
                     82:  *
                     83:  * [14] CharData       ::=   [^<&]* - ([^<&]* ']]>' [^<&]*)
                     84:  * [14]  status: not implemented
                     85:  *
                     86:  * [15] Comments       ::=   '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
                     87:  * [15]  status: not implemented
                     88:  *
                     89:  * [16] PI             ::=   '<?' PITarget (S (Char* - (Char* '?<' Char*)))? '?>'
                     90:  * [16]  status: not implemented
                     91:  *
                     92:  * [17] PITarget       ::=   Name - (('X' | 'x') ('M' | 'm') | ('L' | 'l'))
                     93:  * [17]  status: not implemented
                     94:  *
                     95:  * [18] CDsect         ::=   CDStart CData CDend
                     96:  * [18]  status: not implemented
                     97:  *
                     98:  * [19] CDStart        ::=   '<![CDATA['
                     99:  * [19]  status: not implemented
                    100:  *
                    101:  * [20] CData          ::=   (Char* - (Char* ']]>' Char*))
                    102:  * [20]  status: not implemented
                    103:  *
                    104:  * [21] CDEnd          ::=   ']]>'
                    105:  * [21]  status: not implemented
                    106:  *
                    107:  * [22] prolog         ::=   XMLDecl? Misc* (doctypedecl Misc*)?
                    108:  * [22]  status: partially
                    109:  *
                    110:  * [23] XMLDecl        ::=   '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
                    111:  * [23]  status: ok
                    112:  *
                    113:  * [24] VersionInfo    ::=   S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
                    114:  * [24]  status: ok
                    115:  *
                    116:  * [25] Eq             ::=   S? '=' S?
                    117:  * [25]  status: ok
                    118:  *
                    119:  * [26] VersionNum     ::=   '1.0'
                    120:  * [26]  status: ok
                    121:  *
                    122:  * [27] Misc           ::=   Comment | PI | S
                    123:  * [27]  status: not implemented
                    124:  *
                    125:  * [28] doctypedecl    ::=   '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubsect ']' S?)? '>'
                    126:  * [28]  status: not implemented
                    127:  *
                    128:  * [28a] DeclSep       ::=   PEReference | S
                    129:  * [28a]  status: not implemented
                    130:  *
                    131:  * [28b] intSubset     ::=   (markupdecl | DeclSep)*
                    132:  * [28b]  status: not implemented
                    133:  *
                    134:  * [29] markupdecl     ::=   elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
                    135:  * [29]  status: not implemented
                    136:  *
                    137:  * [30] extSubset      ::=   TextDecl? extSubsetDecl
                    138:  * [30]  status: not implemented
                    139:  *
                    140:  * [31] extSubsetDecl  ::=   ( markupdecl | conditionalSect | DeclSep) *
                    141:  * [31]  status: not implemented
                    142:  *
                    143:  * [32] SDDecl          ::=   S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"'" ('yes' | 'no') '"'))
                    144:  * [32]  status: ok
                    145:  *
                    146:  * 
                    147:  * ** productions 33 through 39 have been removed. It seems that this
                    148:  * ** productions were supporting xml:lang stuff that is easily
                    149:  * ** supported by using directily the xml standard rather than
                    150:  * ** mention it as an special production inside the language.
                    151:  *  
                    152:  * [39] element        ::=   EmptyElemTag | Stag content ETag
                    153:  * [39]  status: not implemented
                    154:  *
                    155:  * [40] Stag           ::=   '<' Name (S Attribute)* S? '>'
                    156:  * [40]  status: not implemented
                    157:  *
                    158:  * [41] Attribute      ::=   Name Eq AttValue
                    159:  * [41]  status: not implemented
                    160:  *
                    161:  * [42] ETag           ::=   '</' Name S? '>'
                    162:  * [42]  status: not implemented
                    163:  *
                    164:  * [43] content        ::=   CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
                    165:  * [43]  status: not implemented
                    166:  *
                    167:  * [44] EmptyElemTag   ::=   '<' Name (S Attribute)* S? '/>'
                    168:  * [44]  status: not implemented
                    169:  *
                    170:  * [45] elementdecl    ::=   '<!ELEMENT' S Name S contentspec S? '>' 
                    171:  * [45]  status: not implemented
                    172:  *
                    173:  * [46] contentspec    ::=   'EMPTY' | 'ANY' | Mixed | children
                    174:  * [46]  status: not implemented
                    175:  *
                    176:  * [47] children       ::=   (choice | seq) ('?' | '*' | '+')? 
                    177:  * [47]  status: not implemented
                    178:  *
                    179:  * [48] cp             ::=   (Name | choice | seq) ('?' | '*' | '+')? 
                    180:  * [48]  status: not implemented
                    181:  *
                    182:  * [49] choice         ::=   '(' S? cp ( S? '|' S? cp)+ S? ')'
                    183:  * [49]  status: not implemented
                    184:  *
                    185:  * [50] seq            ::=   '(' S? cp ( S? ',' S? cp )* S? ')'
                    186:  * [50]  status: not implemented
                    187:  *
                    188:  * [51] Mixed          ::=   '(' '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
                    189:  * [51]  status: not implemented
                    190:  *
                    191:  * [52] AttlistDecl    ::=   '<!ATTLIST' S Name AttDef* S? '>'
                    192:  * [52]  status: not implemented
                    193:  *
                    194:  * [53] AttDef         ::=   S Name S AttType S DefaultDecl
                    195:  * [53]  status: not implemented
                    196:  *
                    197:  * [54] AttType        ::=   Stringtype | TokenizedType | Enumeratedtype
                    198:  * [54]  status: not implemented
                    199:  *
                    200:  * [55] StringType     ::=   'CDATA'
                    201:  * [55]  status: not implemented
                    202:  *
                    203:  * [56] tokenized      ::=   'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
                    204:  * [56]  status: not implemented
                    205:  *
                    206:  * [57] EnumeratedType ::=   NotationType | Enumeration
                    207:  * [57]  status: not implemented
                    208:  *
                    209:  * [58] NotationType   ::=   'NOTATION' S '(' S? Name (S? Name (S? '|' S? Name)* S? ')'
                    210:  * [58]  status: not implemented
                    211:  *
                    212:  * [59] Enumeration    ::=   '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
                    213:  * [59]  status: not implemented
                    214:  *
                    215:  * [60] DefaultDecl    ::=   '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
                    216:  * [60]  status: not implemented
                    217:  *
                    218:  * [61] conditionalSect  ::= includeSect | ignoreSect
                    219:  * [61]  status: not implemented
                    220:  *
                    221:  * [62] includeSect    ::= '<![' S? 'INCLUDE S? '[' extSubsetDecl ']]>'
                    222:  * [62]  status: not implemented
                    223:  *
                    224:  * [63] ignoreSect     ::=  <![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
                    225:  * [63]  status: not implemented
                    226:  *
                    227:  * [64] ignoreSectContents ::=  Ignore ('<![' ignoreSectContents ']]>' Ignore) *
                    228:  * [64]  status: not implemented
                    229:  *
                    230:  * [65] Ignore         ::=  Char * - (Char * ('<!' | ']]>') Char *)
                    231:  * [65]  status: not implemented
                    232:  *
                    233:  * [66] CharRef        ::=  '&#' [0-9]+ ';' | '&#x' [0-9a-FA-F]+ ';'
                    234:  * [66]  status: not implemented
                    235:  *
                    236:  * [67] Reference      ::=  EntityRef | CharRef
                    237:  * [67]  status: not implemented
                    238:  *
                    239:  * [68] EntityRef      ::=  '&' Name ';'
                    240:  * [68]  status: not implemented
                    241:  *
                    242:  * [69] PEReference    ::=  '%' Name ';'
                    243:  * [69]  status: not implemented
                    244:  *
                    245:  * [70] EntityDecl     ::=  GEDecl | PEDecl
                    246:  * [70]  status: not implemented
                    247:  *
                    248:  * [71] GEDecl         ::=  '<!ENTITY' S Name S EntityDef S? '>'
                    249:  * [71]  status: not implemented
                    250:  *
                    251:  * [72] PEDecl         ::=  '<!ENTITY' S '%' S Name S PEDef S? '>'
                    252:  * [72]  status: not implemented
                    253:  *
                    254:  * [73] EntityDef      ::=  EntityValue | (ExternalID NDataDecl?)
                    255:  * [73]  status: not implemented
                    256:  *
                    257:  * [74] PEDef          ::=  EntityValue | ExternalID
                    258:  * [74]  status: not implemented
                    259:  *
                    260:  * [75] ExternalID     ::=  'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
                    261:  * [75]  status: not implemented
                    262:  *
                    263:  * [76] NDataDecl      ::=  S 'NData' S Name
                    264:  * [76]  status: not implemented
                    265:  *
                    266:  * [77] TextDecl       ::=  '<?xml' VersionInfo? EncodingDecl S? '?>'
                    267:  * [77]  status: not implemented
                    268:  *
                    269:  * [78] extParseEnt    ::=  TextDecl? content
                    270:  * [78]  status: not implemented
                    271:  *
                    272:  * [80] EncodingDecl   ::=  S 'encoding' Eq ( '"' EncName '"' | "'" EncName "'" )
                    273:  * [80]  status: ok
                    274:  *
                    275:  * [81] EncName        ::=  [A-Za-z] ([A-Za-z0-9._] | '-')*
                    276:  * [81]  status: ok
                    277:  *
                    278:  * [82] NotationalDecl ::=  '<!NOTATION' S Name S (ExternalID | PublicID) S? '>' 
                    279:  * [82]  status: not implemented
                    280:  *
                    281:  * [83] PublicID       ::=  'PUBLIC' S PubidLiteral
                    282:  * [83]  status: not implemented
                    283:  *
                    284:  * 
                    285:  * 
                    286:  * 
                    287:  */
                    288: 
                    289: /**
                    290:  * \defgroup axl_doc_module Axl Doc: XML Documents related functions, loading XML documents and using them.
                    291:  */
                    292: 
                    293: /** 
                    294:  * \addtogroup axl_doc_module
                    295:  * @{
                    296:  */
                    297: 
                    298: #include <axl.h>
                    299: #include <sys/stat.h>
                    300: #include <sys/types.h>
                    301: #include <fcntl.h>
                    302: 
                    303: 
                    304: #define LOG_DOMAIN "axl-doc"
                    305: 
                    306: struct _axlDoc {
                    307:        /** 
                    308:         * @internal
                    309:         * @brief A reference to the very first axlNode this axlDoc
                    310:         * has. 
                    311:         */
                    312:        axlNode * rootNode;
                    313: 
                    314:        /** 
                    315:         * @internal
                    316:         * The document version.
                    317:         */
                    318:        char * version;
                    319: 
                    320:        /** 
                    321:         * @internal
                    322:         * @brief Current xml encoding document.
                    323:         */
                    324:        char        * encoding;
                    325:        /**
                    326:         * @internal
                    327:         * @brief Current entity encoding detected.
                    328:         */ 
                    329:        const char  * detected_encoding;
                    330:        
                    331:        /** 
                    332:         * @internal If the document was found in a different encoding
                    333:         * than utf-8, this variable will hold its associated value to
                    334:         * allow returning to the original encoding.
                    335:         */
                    336:        char        * encoding_found;
                    337:        
                    338:        /** 
                    339:         * @internal
                    340:         * @brief Current standalone configuration of the given \ref
                    341:         * axlDoc object.
                    342:         */
                    343:        axl_bool    standalone;
                    344: 
                    345:        /** 
                    346:         * @internal
                    347:         *
                    348:         * @brief Parent node stack. This stack is used to control how
                    349:         * are nested nodes while creating/parsing xml files. This
                    350:         * nesting allows to not only properly contruct the xml but
                    351:         * also to check if it is well balanced.
                    352:         */
                    353:        axlStack  * parentNode;
                    354: 
                    355:        /** 
                    356:         * @internal Binary stack to hold the xml:space preserve
                    357:         * status on each level (associated to the current node).
                    358:         */
                    359:        axlBinaryStack * xmlPreserve;
                    360: 
                    361:        /** 
                    362:         * @internal
                    363:         * 
                    364:         * @brief Internal list to hold all PI targets readed.
                    365:         */
                    366:        axlList   * piTargets;
                    367: 
                    368:        /** 
                    369:         * @internal
                    370:         *
                    371:         * @brief Instruct the \ref axlDoc instance to notify that the
                    372:         * xml header have been defined. This helps to allow define PI
                    373:         * instruction that are only found inside the root document,
                    374:         * or after the xml header definition.
                    375:         */
                    376:        axl_bool    headerProcess;
                    377: 
                    378:        /** 
                    379:         * @internal Factory to create items in a memory efficient
                    380:         * manner.
                    381:         */
                    382:        axlFactory * item_factory;
                    383: 
                    384:        /** 
                    385:         * @internal Factory to create nodes in a memory efficient
                    386:         * manner.
                    387:         */
                    388:        axlFactory    * node_factory;
                    389: 
                    390:        /** 
                    391:         * @internal Factory to create nodes to hold content elements.
                    392:         */
                    393:        axlFactory    * content_factory;
                    394: 
                    395:        /** 
                    396:         * @internal Factory to create nodes to hold attribute
                    397:         * elements.
                    398:         */
                    399:        axlFactory    * attr_factory;
                    400: 
                    401:        /** 
                    402:         * @internal Factory to alloc strings.
                    403:         */
                    404:        axlStrFactory * str_factory;
                    405: };
                    406: 
                    407: struct _axlPI {
                    408:        /** 
                    409:         * @internal
                    410:         * 
                    411:         * @brief PI Target name.
                    412:         */
                    413:        char * name;
                    414:        /** 
                    415:         * @internal
                    416:         * 
                    417:         * @brief PI target content.
                    418:         */
                    419:        char * content;
                    420: };
                    421: 
                    422: /* global references to handlers and user defined configuration */
                    423: axlDocDetectCodification detect_codification_func;
                    424: axlPointer               detect_codification_data;
                    425: 
                    426: axlDocConfigureCodification configure_codification_func;
                    427: axlPointer                  configure_codification_data;
                    428: 
                    429: /** 
                    430:  * @internal
                    431:  *
                    432:  * @brief Creates a new empty \ref axlDoc reference.
                    433:  *
                    434:  * Creates the parent stack used for parsing functions.
                    435:  * 
                    436:  * @return A newly allocated \ref axlDoc reference.
                    437:  */
                    438: axlDoc * __axl_doc_new (axl_bool create_parent_stack) 
                    439: {
                    440:        axlDoc    * result = axl_new (axlDoc, 1);
                    441: 
                    442:        /* default container lists */
                    443:        result->parentNode   = axl_stack_new (NULL);
                    444:        result->piTargets    = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_pi_free);
                    445:        result->xmlPreserve  = axl_binary_stack_new ();
                    446: 
                    447:        /* create factories */
                    448:        result->item_factory    = axl_item_factory_create ();
                    449:        result->node_factory    = axl_node_factory_create ();
                    450:        result->content_factory = axl_item_content_factory_create ();
                    451:        result->attr_factory    = axl_item_attr_factory_create ();
                    452:        result->str_factory     = axl_string_factory_create ();
                    453:        return result;
                    454: }
                    455: 
                    456: /** 
                    457:  * @internal
                    458:  *
                    459:  * Clears internal axlDoc variables used mainly to parse documents.
                    460:  * 
                    461:  * @param doc The \ref axlDoc to clear
                    462:  */
                    463: void __axl_doc_clean (axlDoc * doc)
                    464: {
                    465:        /* release memory used by the parser */
                    466:        if (doc->parentNode != NULL) {
                    467:                axl_stack_free (doc->parentNode);
                    468:                doc->parentNode = NULL;
                    469:        }
                    470: 
                    471:        return;
                    472: }
                    473: 
                    474: /** 
                    475:  * @internal Function used by the axl doc module to allocate memory to
                    476:  * be used by the axl stream. Currently this is used to alloc xml node
                    477:  * names and xml attribute key and its value. The rest of items are
                    478:  * allocated by the system memory allocation.
                    479:  * 
                    480:  * @param size The size that is required by the axl stream to be allocated.
                    481:  *
                    482:  * @param doc The axlDoc reference, which contains a reference to the
                    483:  * string factory used to allocate memory.
                    484:  * 
                    485:  * @return A reference to the allocated memory. 
                    486:  */
                    487: char * __axl_doc_alloc (int size, axlDoc * doc)
                    488: {
                    489:        /* just return a piece of memory */
                    490:        return axl_string_factory_alloc (doc->str_factory, size);
                    491: }
                    492: 
                    493: /** 
                    494:  * @internal Internal function that tries to check encoding found to
                    495:  * configure the proper set of functions to translate from and to
                    496:  * utf-8.
                    497:  * 
                    498:  * @param doc The document being configured.
                    499:  *
                    500:  * @param error An optional error that will be filled in the case an
                    501:  * error is found.
                    502:  * 
                    503:  * @return axl_true if the operation was completed, otherwise axl_false is
                    504:  * returned.
                    505:  */
                    506: axl_bool axl_doc_configure_encoding (axlDoc * doc, axlStream * stream, axlError ** error)
                    507: {
                    508:        char     * encoding = NULL;
                    509:        axl_bool   result;
                    510:        
                    511:        /* normalize encoding found */
                    512:        if (doc->encoding) {
                    513:                /* copy encoding */
                    514:                encoding = axl_strdup (doc->encoding);
                    515: 
                    516:                /* trim encoding */
                    517:                axl_stream_trim (encoding);
                    518: 
                    519:                /* remove characters not required */
                    520:                axl_stream_remove (encoding, "-", axl_false);
                    521:                axl_stream_remove (encoding, "_", axl_false); 
                    522: 
                    523:                /* make it lower case */
                    524:                axl_stream_to_lower (encoding);
                    525:                
                    526:        } /* end if */
                    527:        
                    528:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "configuring final document enconding, previously detected=%s, declared=%s",
                    529:                   doc->detected_encoding ? doc->detected_encoding : "none",
                    530:                   encoding ? encoding : "none");
                    531: 
                    532:        /* do not perform any configuration if nothing is defined */
                    533:        if (! configure_codification_func) {
                    534:                axl_free (encoding);
                    535:                return axl_true;
                    536:        }
                    537: 
                    538:        /* call to configure encoding */
                    539:        result = configure_codification_func (stream, encoding, doc->detected_encoding, configure_codification_data, error);
                    540:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "result from configure encoding function=%d", result);
                    541: 
                    542:        if (result) {
                    543:                /* encoding was fine, that means we are working in
                    544:                 * utf-8, udate document internals to move encoding to
                    545:                 * utf-8 */
                    546:                doc->encoding_found = encoding;
                    547:                encoding            = NULL;
                    548: 
                    549:                /* reset encoding found to the new value */
                    550:                if (doc->encoding)
                    551:                        axl_free (doc->encoding);
                    552:                doc->encoding       = axl_strdup ("utf-8");
                    553:        }
                    554:        axl_free (encoding);
                    555: 
                    556:        return result;
                    557: }
                    558: 
                    559: /** 
                    560:  * @internal
                    561:  * 
                    562:  * @brief Support for parsing the xml entity header 
                    563:  * 
                    564:  * @param stream The axlStream where is expected to receive the xml
                    565:  * header
                    566:  *
                    567:  * @param doc The axlDoc where the header configuration will be
                    568:  * placed.
                    569:  *
                    570:  * @param error An optional error that will be filled in the case an
                    571:  * error is found.
                    572:  *
                    573:  * @return It is supposed that the function return \ref axl_true, an
                    574:  * not deallocation is performed, and all elements were parsed
                    575:  * properly. In the case \ref axl_false is returned, memory associated
                    576:  * with the given stream will be released. If the document is
                    577:  * associated, it will also be released.
                    578:  */
                    579: axl_bool __axl_doc_parse_xml_header (axlStream * stream, axlDoc * doc, axlError ** error)
                    580: {
                    581:        char      * string_aux;
                    582:        int         size;
                    583: 
                    584:        /* check if the user is defining the header many times */
                    585:        if (doc->headerProcess) {
                    586:                axl_error_new (-1, "Found a new xml header expecification. Only one header is allowed for each xml document.", stream, error);
                    587:                axl_stream_free (stream);
                    588:                return axl_false;
                    589:        }
                    590: 
                    591:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "looking for an xml header declaration");
                    592: 
                    593:        /* check for initial XMLDec (production 23) */
                    594:        if (axl_stream_inspect (stream, "<?", 2)) {
                    595:                
                    596:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml declaration");
                    597: 
                    598:                /* check initial <?xml xml header */
                    599:                if (! (axl_stream_inspect (stream, "xml", 3) > 0)) {
                    600:                        axl_error_new (-2, "expected initial <?xml declaration, not found.", stream, error);
                    601:                        axl_stream_free (stream);
                    602:                        return axl_false;
                    603:                }
                    604:                
                    605:                /* consume spaces */
                    606:                AXL_CONSUME_SPACES (stream);
                    607: 
                    608:                if (! axl_stream_inspect (stream, "version=", 8)) {
                    609:                        axl_error_new (-2, "expected to find 'version=' declaration, not found.", stream, error);
                    610:                        axl_stream_free (stream);
                    611:                        return axl_false;
                    612:                }
                    613: 
                    614:                /* consume spaces */
                    615:                AXL_CONSUME_SPACES (stream);
                    616: 
                    617:                /* check for " or ' */
                    618:                if (! axl_stream_inspect_several (stream, 2, "\"1.0\"", 5, "'1.0'", 5)) {
                    619:                        axl_error_new (-2, "expected to find either \" or ' while procesing version number, not found.", stream, error);
                    620:                        axl_stream_free (stream);
                    621:                        return axl_false;
                    622:                }
                    623: 
                    624:                /* check for an space */
                    625:                AXL_CONSUME_SPACES(stream);
                    626: 
                    627:                /* now check for encoding */
                    628:                if (axl_stream_inspect_several (stream, 2, "encoding=\"", 10, "encoding='", 10) > 0) {
                    629: 
                    630:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found encoding declaration");
                    631: 
                    632:                        /* found encoding instruction */
                    633:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, "'", "\"");
                    634:                        if (string_aux == NULL) {
                    635:                                axl_error_new (-2, "expected encoding value, not found.", stream, error);
                    636:                                axl_stream_free (stream);
                    637:                                return axl_false;
                    638:                        }
                    639: 
                    640:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "encoding found=%s", string_aux);
                    641: 
                    642:                        /* set document encoding: do not allocate
                    643:                         * twice the string returned, just nullify
                    644:                         * stream internal reference and use the same
                    645:                         * reference */
                    646:                        axl_stream_nullify (stream, LAST_CHUNK);
                    647:                        doc->encoding = string_aux;
                    648: 
                    649:                }
                    650: 
                    651:                /* check for an space */
                    652:                AXL_CONSUME_SPACES(stream);
                    653: 
                    654:                /* get standalone configuration */
                    655:                if ((axl_stream_inspect_several (stream, 2, "standalone=\"", 12, "standalone='", 12) > 0)) {
                    656:                        
                    657:                        /* found standalone instruction */
                    658:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, "'", "\"");
                    659:                        if (string_aux == NULL) {
                    660:                                axl_error_new (-2, "expected to receive standalone value, not found.", stream, error);
                    661:                                axl_stream_free (stream);
                    662:                                return axl_false;
                    663:                        }
                    664: 
                    665:                        /* set standalone configuration */
                    666:                        if (memcmp ("yes", string_aux, 3))
                    667:                                doc->standalone = axl_false;
                    668:                        else
                    669:                                doc->standalone = axl_true;
                    670:                }
                    671:                
                    672:                /* check for an space */
                    673:                AXL_CONSUME_SPACES(stream);
                    674: 
                    675:                /* get the trailing header */
                    676:                if (! (axl_stream_inspect (stream, "?>", 2) > 0)) {
                    677:                        axl_error_new (-2, "expected to receive the xml trailing header ?>, not found.", stream, error);
                    678:                        axl_stream_free (stream);
                    679:                        return axl_false;
                    680:                }
                    681: 
                    682:                /* consume a possible comment */
                    683:                if (! axl_doc_consume_comments (doc, stream, error))
                    684:                        return axl_false;
                    685:        }
                    686: 
                    687:        /* configure encoding again, now we could have more data */
                    688:        if (! axl_doc_configure_encoding (doc, stream, error)) {
                    689:                axl_stream_free (stream);
                    690:                return axl_false;
                    691:        }
                    692: 
                    693:        /* now process the document type declaration */
                    694:        if (axl_stream_inspect (stream, "<!DOCTYPE", 9) > 0) {
                    695:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found doc type declaration..");
                    696:                /* found document type declaration, just skip it for
                    697:                 * now */
                    698:                axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &size, 1, ">");
                    699: 
                    700:                /* consume a possible comment */
                    701:                if (! axl_doc_consume_comments (doc, stream, error))
                    702:                        return axl_false;
                    703:        }
                    704: 
                    705:        /* return AXL_TRUE value */
                    706:        return axl_true;
                    707: }
                    708: 
                    709: /** 
                    710:  * @internal
                    711:  *
                    712:  * @brief Tries to parse the first (and compulsory) node that the xml
                    713:  * document must have.
                    714:  *
                    715:  * The very minimal expresion of an xml document is the one defined by
                    716:  * only one node, with no content and no attributes. This minimal xml
                    717:  * could be defined as:
                    718:  *
                    719:  * \code
                    720:  *   <hello/>
                    721:  * \endcode
                    722:  *
                    723:  * Or the other form accepted:
                    724:  *
                    725:  * \code
                    726:  *   <hello />
                    727:  * \endcode
                    728:  *
                    729:  * 
                    730:  * 
                    731:  * 
                    732:  * @param stream The \ref axlStream object where is expected to find
                    733:  * the xml node content.
                    734:  *
                    735:  * @param doc The \ref axlDoc object where node read will be placed
                    736:  * inside.
                    737:  * 
                    738:  * @param node The node that has been added due to calling to this
                    739:  * function.
                    740:  *
                    741:  * @param error An optional error reporting variable to used to report
                    742:  * upper level the error found.
                    743:  * 
                    744:  * @return axl_true if the first node was successfully parsed or
                    745:  * axl_false if not. If the function find something wrong the document
                    746:  * is unrefered.
                    747:  */
                    748: axl_bool __axl_doc_parse_node (axlStream   * stream, 
                    749:                               axlDoc      * doc, 
                    750:                               axlNode    ** calling_node, 
                    751:                               axl_bool    * is_empty, 
                    752:                               axlError   ** error)
                    753: {
                    754:        char    * string_aux;
                    755:        char    * string_aux2;
                    756:        axlNode * node;
                    757:        int       matched_chunk;
                    758:        int       length;
                    759:        axl_bool  delim;
                    760:        
                    761:        /* consume a possible comment */
                    762:        if (! axl_doc_consume_comments (doc, stream, error))
                    763:                return axl_false;
                    764: 
                    765:        /* check for initial < definition */
                    766:        if (! (axl_stream_inspect (stream, "<", 1) > 0)  && ! axl_stream_remains (stream)) {
                    767:                /* check if we are reading the first node node */
                    768:                if (doc->rootNode == NULL)
                    769:                        axl_error_new (-2, "expected initial < for a root node definition, not found. An xml document must have, at least, one node definition.", 
                    770:                                       stream, error);
                    771:                else
                    772:                        axl_error_new (-2, "expected initial < for a node definition, not found.", stream, error);
                    773:                axl_stream_free (stream);
                    774:                return axl_false;
                    775:        }
                    776: 
                    777:        /* get node name, keeping in mind the following:
                    778:         * chunk_matched
                    779:         * >  : 0
                    780:         * /> : 1
                    781:         * " ": 2
                    782:         *
                    783:         * We also reconfigure the alloc method used by the axl stream
                    784:         * to ensure that the module name is allocated through the
                    785:         * string factory.
                    786:         */
                    787:        axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
                    788:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 2, ">", " ");
                    789: 
                    790:        /* nullify */
                    791:        axl_stream_nullify (stream, LAST_CHUNK);
                    792: 
                    793:        if (AXL_IS_STR_EMPTY (string_aux)) {
                    794:                /* use alloc though string factory */
                    795:                axl_stream_set_buffer_alloc (stream, NULL, NULL);
                    796: 
                    797:                axl_error_new (-2, "expected an non empty content for the node name not found.", stream, error);
                    798:                axl_stream_free (stream);
                    799:                return axl_false;
                    800:        }
                    801:        
                    802:        /* if found a '/', it is matched as 1 */
                    803:        if (matched_chunk == 1)
                    804:                matched_chunk = 2;
                    805:        else {
                    806:                /* get the string length */
                    807:                length = strlen (string_aux);
                    808: 
                    809:                /* if matched / it means that it was readed />, remove
                    810:                 * it and all white spaces */
                    811:                if (string_aux[length - 1] == '/') {
                    812:                        /* flag as matched /> */
                    813:                        matched_chunk          = 1;
                    814:                        string_aux[length - 1] = 0;
                    815:                } /* end if */
                    816:        } /* end if */
                    817: 
                    818:        /* create the node and associate it the node name found */
                    819:        node = axl_node_factory_get (doc->node_factory);
                    820:        axl_node_set_name_from_factory (node, string_aux); 
                    821: 
                    822:        if (doc->rootNode == NULL) {
                    823:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting as first node found, the root node: <%s>", string_aux);
                    824: 
                    825:                doc->rootNode  = node;
                    826:                
                    827:                /* set the node read, the root one, to be the parent */
                    828:                axl_stack_push (doc->parentNode, node);
                    829: 
                    830:                /* configure the node */
                    831:                axl_node_set_doc (node, doc);
                    832: 
                    833:        } else {
                    834:                /* or set the node as a child of the current parent */
                    835:                axl_doc_set_child_current_parent (doc, node);
                    836:        }
                    837: 
                    838:        /* set the node created to the calling node, so the caller
                    839:         * could get a reference */
                    840:        if (calling_node != NULL)
                    841:                *calling_node = node;
                    842: 
                    843:        /* only consume white spaces if matched_chunk is 2 */
                    844:        if (matched_chunk == 2) {
                    845:                /* get rid from spaces */
                    846:                AXL_CONSUME_SPACES (stream);
                    847:        }
                    848: 
                    849:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node found: [%s]", string_aux);
                    850: 
                    851: 
                    852:        /* now, until the node ends, we have to find the node
                    853:         * attributes or the node defintion end */
                    854:        while (1) {
                    855:                /* check if we have an attribute for the node, or the node
                    856:                 * definition have ended or the node definition is an empty
                    857:                 * one 
                    858:                 * 
                    859:                 * the following code that relies on matched_chunk is
                    860:                 * done due to previous call to get_until function. If
                    861:                 * the value 0 or 1 was matched, this means that we
                    862:                 * are on "/>" case */
                    863:                if ((matched_chunk == 1) ||
                    864:                    axl_stream_inspect (stream, "/>", 2) > 0) {
                    865:                        /* use alloc though string factory */
                    866:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
                    867: 
                    868:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found end xml node definition '/>'");
                    869: 
                    870:                        /* empty node configuration found */
                    871:                        *is_empty = axl_true;
                    872:                        /* axl_node_set_is_empty (node, axl_true); */
                    873: 
                    874:                        /* make this node to be completed and no child
                    875:                         * could be set. */
                    876:                        axl_stack_pop (doc->parentNode);
                    877: 
                    878:                        /* set the parent node to receive all content
                    879:                         * found in the next parsing elements because
                    880:                         * the element found is totally empty */
                    881:                        *calling_node = axl_stack_peek (doc->parentNode);
                    882:                        return axl_true;
                    883:                }
                    884:                
                    885:                /* check if we have an attribute for the node, or the node
                    886:                 * definition have ended or the node definition is an empty
                    887:                 * one 
                    888:                 * 
                    889:                 * the following code that relies on matched_chunk is
                    890:                 * done due to previous call to get_until function. If
                    891:                 * the value 2 or 3 was matched, this means that we
                    892:                 * are on ">" case */
                    893:                if ((matched_chunk == 0) ||
                    894:                    (axl_stream_inspect (stream, ">", 1) > 0)) {
                    895:                        /* use alloc though string factory */
                    896:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
                    897:                        
                    898:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found [end] xml node definition '>', for node: [%s]",
                    899:                                   axl_node_get_name (node));
                    900: 
                    901:                        /* flag that the node is an empty definition */
                    902:                        *is_empty = axl_false;
                    903: 
                    904:                        /* this node is ended */
                    905:                        return axl_true;
                    906:                }
                    907:                
                    908:                /* get rid from spaces */
                    909:                AXL_CONSUME_SPACES (stream);
                    910: 
                    911:                /* found attribute declaration, try to read it.
                    912:                 *
                    913:                 * We also reconfigure the alloc method used by the
                    914:                 * axl stream to ensure that xml node attributes are
                    915:                 * allocated through the string factory.
                    916:                 */
                    917:                string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "=");
                    918:                if (string_aux != NULL) {
                    919:                        /* nullify internal reference to the stream:
                    920:                         * now we have inside string_aux the attribute
                    921:                         * name */
                    922:                        axl_stream_nullify (stream, LAST_CHUNK);
                    923: 
                    924:                        /* check for empty values at the attribute definition */
                    925:                        if (string_aux [0] == 0) {
                    926:                                axl_error_new (-5, "Expected to find an attribute name (but found an empty value)", stream, error);
                    927:                                axl_stream_free (stream);
                    928:                                return axl_false;
                    929:                        } /* end if */
                    930: 
                    931:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attribute found: [%s]", string_aux);
                    932: 
                    933:                        /* remove next " and ' if defined */
                    934:                        /* flag the we are looking for a " */
                    935:                        delim = axl_true;
                    936:                        if (! ((axl_stream_inspect (stream, "\"", 1) > 0))) {
                    937:                                /* seems it is not found, flag we are
                    938:                                 * looking for ' */
                    939:                                delim = axl_false;
                    940:                                if (! (axl_stream_inspect (stream, "\'", 1) > 0)) {
                    941:                                        /* use alloc though string factory */
                    942:                                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
                    943: 
                    944:                                        axl_error_new (-2, "Expected to find an attribute value initiator (\") or ('), every attribute value must start with them", 
                    945:                                                       stream, error);
                    946:                                        axl_stream_free (stream);
                    947:                                        return axl_false;
                    948:                                }
                    949:                        }
                    950:                        
                    951:                        
                    952:                        /* now get the attribute value */
                    953:                        if (delim)
                    954:                                string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\"");
                    955:                        else
                    956:                                string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "'");
                    957: 
                    958:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "value found: [%s]", string_aux2);
                    959:                        
                    960:                        /* nullify internal reference so we have the
                    961:                         * only one reference to attribute value
                    962:                         * inside string_aux2 */
                    963:                        axl_stream_nullify (stream, LAST_CHUNK);
                    964: 
                    965:                        if (axl_node_has_attribute (node, string_aux)) {
                    966:                                /* parse error */
                    967:                                axl_error_new (-3, "Unable to add attribute to node which already has this attribute. Duplicate attribute error.", stream, error);
                    968:                                axl_stream_free (stream);
                    969:                                return axl_false;
                    970:                        } /* end if */
                    971:                        
                    972:                        /* set a new attribute for the given node */
                    973:                        axl_node_set_attribute_from_factory (doc->attr_factory, node, string_aux, string_aux2);
                    974: 
                    975:                        /* check xml:space configuration and update binary stack */
                    976:                        if (axl_cmp (string_aux, "xml:space")) {
                    977:                                if (axl_cmp (string_aux2, "preserve")) {
                    978:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml:space=preseve, notifying..");
                    979: 
                    980:                                        /* 1: xml:space=preserve (found)
                    981:                                         * make current node and all its childs to preserve (by
                    982:                                         * default) all white spaces found */
                    983:                                        axl_binary_stack_push (doc->xmlPreserve, axl_true);
                    984: 
                    985:                                } else if (axl_cmp (string_aux2, "default")) {
                    986:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found xml:space=default, notifying..");
                    987: 
                    988:                                        /* 2: xml:space=default  (found)
                    989:                                         * make current node and all its childs to not
                    990:                                         * preserve white spaces (by default) */
                    991:                                        axl_binary_stack_push (doc->xmlPreserve, axl_false);
                    992:                                } else {
                    993:                                        /* parse error */
                    994:                                        axl_error_new (-2, "xml:space attribute found with other value than 'preserve' or 'default', this is not allowed.", stream, error);
                    995:                                        axl_stream_free (stream);
                    996:                                        return axl_false;
                    997: 
                    998:                                } /* end if */
                    999:                        } else {
                   1000:                                /* 3: xml:space (not found) 
                   1001:                                 * make the current node to inherint
                   1002:                                 * default from parent */
                   1003:                                if (axl_binary_stack_is_empty (doc->xmlPreserve))
                   1004:                                        axl_binary_stack_push (doc->xmlPreserve, axl_false);
                   1005:                                else
                   1006:                                        axl_binary_stack_push_the_same (doc->xmlPreserve);
                   1007:                        } /* end if */
                   1008: 
                   1009:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attribute installed..");
                   1010: 
                   1011:                        /* get rid from spaces */
                   1012:                        AXL_CONSUME_SPACES (stream);
                   1013:                        continue;
                   1014:                }
                   1015:                
                   1016:                /* if reached this point, error found */
                   1017:                axl_error_new (-2, "Parse error while reading a node being opened", stream, error);
                   1018:                axl_stream_free (stream);
                   1019:                return axl_false;
                   1020: 
                   1021:        } /* end while */
                   1022:        
                   1023:        /* node properly parsed  */
                   1024:        return axl_true;
                   1025: }
                   1026: 
                   1027: /** 
                   1028:  * @internal
                   1029:  * @brief Perform the close node operation.
                   1030:  *
                   1031:  */
                   1032: axl_bool __axl_doc_parse_close_node (axlStream * stream, axlDoc * doc, axlNode ** _node, axlError ** error)
                   1033: {
                   1034:        char    * string;
                   1035:        int       result_size = -1;
                   1036:        axlNode * node;
                   1037: 
                   1038:        /* get the node being closed to check to the current parent */
                   1039:        string = axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &result_size, 1, ">");
                   1040:        if (string == NULL) {
                   1041:                axl_error_new (-1, "An error was found while closing the xml node", stream, error);
                   1042:                axl_stream_free (stream);
                   1043:                return axl_false;
                   1044:        }
                   1045: 
                   1046:        /* check for optional white space inside the trailing result */
                   1047:        if (axl_stream_is_white_space (string + result_size - 1)) {
                   1048:                /* nullify to remove the optional white spaces */
                   1049:                string [result_size - 1] = 0;
                   1050:        } /* end if */
                   1051: 
                   1052:        /* get current parent node */
                   1053:        node   = axl_stack_peek (doc->parentNode);
                   1054:        if (node == NULL) {
                   1055:                axl_error_new (-1, "Found that the stack doesn't have any node opened, this means either an libaxl error or the xml being read is closing a node not opened",
                   1056:                               stream, error);
                   1057:                axl_stream_free (stream);
                   1058:                return axl_false;
                   1059:        }
                   1060:        
                   1061:        /* check current axl node name against closed string */
                   1062:        if (axl_cmp (axl_node_get_name (node), string)) { 
                   1063: 
                   1064:                /* ok, axl node to be closed is the one expected */
                   1065:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "closing xml node, that matched with parent opened");
                   1066: 
                   1067:                return axl_true;
                   1068:        }
                   1069: 
                   1070:        /* seems that the node being closed doesn't match */
                   1071:        __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "xml node names to be closed doesn't matched (%s != %s), current node stack status:",
                   1072:                 axl_node_get_name (node), string);
                   1073: 
                   1074:        node = axl_stack_pop (doc->parentNode);
                   1075:        while (node != NULL) {
                   1076:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "<%s>", axl_node_get_name (node));
                   1077:                node = axl_stack_pop (doc->parentNode);
                   1078:        }
                   1079: 
                   1080:        axl_error_new (-1, "An error was found while closing the opened xml node, parent opened and xml node being closed doesn't match",
                   1081:                       stream, error);
                   1082:        axl_stream_free (stream);
                   1083: 
                   1084:        return axl_false;
                   1085: }
                   1086: 
                   1087: /** 
                   1088:  * @internal
                   1089:  * 
                   1090:  * Internal function which works as a common base for all functions
                   1091:  * that parse XML documents from different inputs.
                   1092:  */
                   1093: axlDoc * __axl_doc_parse_common (const char * entity, int entity_size, 
                   1094:                                  const char * file_path, int fd_handle, 
                   1095:                                 axlError ** error)
                   1096: {
                   1097:        axlStream * stream        = NULL;
                   1098:        axlDoc    * doc           = NULL;
                   1099:        axlNode   * node          = NULL;
                   1100:        char      * string        = NULL;
                   1101:        int         index;
                   1102:        axl_bool    is_empty      = axl_false;
                   1103:        
                   1104:        /* create the xml stream using provided data */
                   1105:        stream         = axl_stream_new (entity, entity_size, file_path, fd_handle, error);
                   1106:        axl_return_val_if_fail (stream, NULL);
                   1107: 
                   1108:        /* create a document reference */
                   1109:        doc            = __axl_doc_new (axl_true);
                   1110:        axl_stream_link (stream, doc, (axlDestroyFunc) axl_doc_free);
                   1111: 
                   1112:        /* detect transitional entity codification to configure built
                   1113:         * decoder (only if defined handler found) */
                   1114:        if (detect_codification_func) {
                   1115:                if (! detect_codification_func (stream, &doc->detected_encoding, detect_codification_data, error)) {
                   1116:                        axl_stream_free (stream);
                   1117:                        return NULL; 
                   1118:                }
                   1119:        } /* end if */
                   1120: 
                   1121:        /* parse initial xml header */
                   1122:        if (!__axl_doc_parse_xml_header (stream, doc, error))
                   1123:                return NULL;
                   1124: 
                   1125:        /* signal that this document have processed its header */
                   1126:        doc->headerProcess = axl_true;
                   1127:        
                   1128:        /* parse the rest of the document, setting as parent NULL
                   1129:         * because still no parent is found. */
                   1130:        if (!__axl_doc_parse_node (stream, doc, &node, &is_empty, error))
                   1131:                return NULL;
                   1132: 
                   1133:        /* if the node returned is not empty */
                   1134:        if (! is_empty) {
                   1135: 
                   1136:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the first node ready, have content, reading it");
                   1137: 
                   1138:                /* while the stream have data */
                   1139:                while (axl_stream_remains (stream)) {
                   1140: 
                   1141:                        /* get current index */
                   1142:                        index = axl_stream_get_index (stream);
                   1143: 
                   1144:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "current index: %d (global: %d)", index,
                   1145:                                   axl_stream_get_global_index (stream));
                   1146:                        
                   1147:                        /* get rid from spaces according to the
                   1148:                         * xml:space configuration */
                   1149:                        if (! axl_binary_stack_peek (doc->xmlPreserve)) {
                   1150:                                AXL_CONSUME_SPACES(stream);
                   1151:                        } /* end if */
                   1152: 
                   1153:                        /* consume a possible comment and process instructions */
                   1154:                        if (axl_stream_peek (stream, "<?", 2) > 0 || axl_stream_peek (stream, "<!--", 4) > 0) {
                   1155:                                if (! axl_doc_consume_comments (doc, stream, error))
                   1156:                                        return NULL;
                   1157:                                
                   1158:                                /* continue on the next index */
                   1159:                                continue;
                   1160:                        } /* end if */
                   1161:                        
                   1162:                        if ((axl_stream_peek (stream, "</", 2) > 0)) {
                   1163:                                /* accept previous peek */
                   1164:                                axl_stream_accept (stream);
                   1165: 
                   1166:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a node termination signal");
                   1167: 
                   1168:                                /* seems that a node is being closed */
                   1169:                                if (! __axl_doc_parse_close_node (stream, doc, &node, error))
                   1170:                                        return NULL;
                   1171: 
                   1172:                                /* because the xml node have been
                   1173:                                 * closed, make the parent to be the
                   1174:                                 * previous one */
                   1175:                                axl_stack_pop (doc->parentNode);
                   1176: 
                   1177:                                /* get the new parent */
                   1178:                                node = axl_stack_peek (doc->parentNode);
                   1179: 
                   1180:                                /* restore previous xml:space value */
                   1181:                                axl_binary_stack_pop (doc->xmlPreserve);
                   1182: 
                   1183:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "node properly closed, current parent node stack size: %d, parent=<%s>",
                   1184:                                           axl_stack_size (doc->parentNode), (node != NULL) ? axl_node_get_name (node) : "--no parent--");
                   1185: 
                   1186:                                if (axl_stack_size (doc->parentNode) > 0)
                   1187:                                        continue;
                   1188:                                break;
                   1189:                        } /* end if */
                   1190: 
                   1191:                        /* check here for CDATA section. This is done
                   1192:                         * here because the following checking could
                   1193:                         * be mixed because they starts with the same:
                   1194:                         * < */
                   1195:                        if ((axl_stream_peek (stream, "<![CDATA[", 9) > 0)) {
                   1196:                                /* accet previous peek */
                   1197:                                axl_stream_accept (stream);
                   1198: 
                   1199:                                /* found CDATA section, get current content */
                   1200:                                axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
                   1201:                                string = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "]]>");
                   1202:                                axl_stream_set_buffer_alloc (stream, NULL, NULL);
                   1203:                                if (string == NULL) {
                   1204:                                        axl_error_new (-1, "Unable to get CDATA content. There was an error.", stream, error);
                   1205:                                        axl_stream_free (stream);
                   1206:                                        return NULL;
                   1207:                                }
                   1208: 
                   1209:                                /* nullify internal reference to the
                   1210:                                 * string_aux so we can use that
                   1211:                                 * memory allocated as our
                   1212:                                 * reference */
                   1213:                                axl_stream_nullify (stream, LAST_CHUNK);
                   1214: 
                   1215:                                /* set current data */
                   1216:                                /* axl_node_set_content_ref (node, string, -1);  */
                   1217:                                axl_node_set_cdata_content_from_factory (doc->content_factory, node, string, -1);
                   1218:                                continue;
                   1219:                        } /* end if */
                   1220: 
                   1221: 
                   1222:                        if ((axl_stream_peek (stream, "<", 1) > 0)) {
                   1223:                                /* accept previous peek */
                   1224:                                axl_stream_accept (stream);
                   1225: 
                   1226:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a new node being opened");
                   1227: 
                   1228:                                /* seems that another node is being opened */
                   1229:                                if (!__axl_doc_parse_node (stream, doc, &node, &is_empty, error))
                   1230:                                        return NULL;
                   1231: 
                   1232:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "finished parsing opened node, current parent=<%s>",
                   1233:                                           axl_node_get_name (node));
                   1234: 
                   1235:                                continue;
                   1236:                        }
                   1237:                        
                   1238:                        /* restore index position previous to the axl
                   1239:                         * space consuming */
                   1240:                        if (axl_stream_get_index (stream) > index) {
                   1241:                                axl_stream_move (stream, index);
                   1242:                        }
                   1243:                        
                   1244:                        /* found node content */
                   1245:                        axl_stream_set_buffer_alloc (stream, (axlStreamAlloc)__axl_doc_alloc, doc);
                   1246:                        string = axl_stream_get_until (stream, NULL, NULL, axl_false, 1, "<");
                   1247:                        axl_stream_set_buffer_alloc (stream, NULL, NULL);
                   1248:                        
                   1249:                        /* check for a null content found */
                   1250:                        if (string == NULL) {
                   1251:                                axl_error_new (-1, "an error was found while reading the xml node content", stream, error);
                   1252:                                axl_stream_free (stream);
                   1253:                                return NULL;
                   1254:                        }
                   1255: 
                   1256:                        /* nullify internal stream reference to have
                   1257:                         * the unique reference */
                   1258:                        axl_stream_nullify (stream, LAST_CHUNK);
                   1259: 
                   1260:                        /* set current data */
                   1261:                        /* axl_node_set_content_ref (node, string, -1); */
                   1262:                        axl_node_set_content_from_factory (doc->content_factory, node, string, -1); 
                   1263: 
                   1264:                        /* keep on looping */
                   1265:                }
                   1266:        }
                   1267: 
                   1268:        /* pop axl parent */
                   1269:        if (! axl_stack_is_empty (doc->parentNode)) {
                   1270:                
                   1271:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, 
                   1272:                           "current parent stack size shows that not all opened nodes were closed. This means that the XML document is not properly balanced (stack size: %d)",
                   1273:                           axl_stack_size (doc->parentNode));
                   1274: 
                   1275:                /* notify error */
                   1276:                axl_error_new (-1, "XML document is not balanced, still remains xml nodes", stream, error);
                   1277:                axl_stream_free (stream);
                   1278: 
                   1279:                return NULL;
                   1280:        }
                   1281: 
                   1282:        /* parse complete */
                   1283:        axl_stream_unlink (stream);
                   1284:        axl_stream_free (stream);
                   1285: 
                   1286:        /* clean document internal variables */
                   1287:        __axl_doc_clean (doc);
                   1288: 
                   1289:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document parse COMPLETED"); 
                   1290: 
                   1291:        return doc;
                   1292: }
                   1293: 
                   1294: /** 
                   1295:  * @brief Creates a new empty xml document, especifying options to be
                   1296:  * used in the header.
                   1297:  *
                   1298:  * This function allows to create the xml document representation the
                   1299:  * must be used to add childs to it.
                   1300:  *
                   1301:  * The following is a simple example that creates a xml document (\ref
                   1302:  * axlDoc) with a single root node (\ref axlNode):
                   1303:  * \code
                   1304:  * // some variables 
                   1305:  * axlDoc  * doc;
                   1306:  * axlNode * node;
                   1307:  *
                   1308:  * // dump content variables
                   1309:  * char    * content;
                   1310:  * int       content_size;
                   1311:  *
                   1312:  * // create the document 
                   1313:  * doc = axl_doc_create (NULL, NULL, axl_true);
                   1314:  *
                   1315:  * // create the root document node
                   1316:  * node = axl_node_create ("root-node");
                   1317:  * 
                   1318:  * // configure it as the root 
                   1319:  * axl_doc_set_root (doc, node);
                   1320:  *
                   1321:  * // dump pretty
                   1322:  * axl_doc_dump_pretty (doc, &content, &content_size, 4);
                   1323:  *
                   1324:  * // print the content and free
                   1325:  * printf ("document size=%d, content: %s\n", content_size, content);
                   1326:  * axl_free (content);
                   1327:  * \endcode
                   1328:  * 
                   1329:  * @param version The xml document version. This value is optional. If
                   1330:  * NULL is used, the library will use "1.0" as version value.
                   1331:  *
                   1332:  * @param encoding The document encoding to be used. This value is
                   1333:  * optional, if NULL is provided, no encoding specification will be
                   1334:  * used.
                   1335:  *
                   1336:  * @param standalone Standalone configuration flag. By default, use
                   1337:  * axl_false.
                   1338:  * 
                   1339:  * @return Returns a newly allocated \ref axlDoc instance that must be
                   1340:  * deallocated by using \ref axl_doc_free.
                   1341:  */
                   1342: axlDoc  * axl_doc_create                   (const char     * version, 
                   1343:                                            const char     * encoding,
                   1344:                                            axl_bool         standalone)
                   1345: {
                   1346:        axlDoc * doc;
                   1347: 
                   1348:        /* create a new reference, without creating  */
                   1349:        doc = __axl_doc_new (axl_false);
                   1350:        
                   1351:        /* save the version */
                   1352:        if (version != NULL)
                   1353:                doc->version  = axl_strdup (version);
                   1354: 
                   1355:        /* save encoding value */
                   1356:        if (encoding != NULL)
                   1357:                doc->encoding = axl_strdup (encoding);
                   1358: 
                   1359:        /* save standalone configuration */
                   1360:        doc->standalone       = standalone;
                   1361:        
                   1362:        /* return the reference created */
                   1363:        return doc;
                   1364: }
                   1365: 
                   1366: /** 
                   1367:  * @internal Returns how many bytes will hold the document provided.
                   1368:  * 
                   1369:  * @param doc The document to measure.
                   1370:  *
                   1371:  * @param pretty_print If pretty print is activated.
                   1372:  * 
                   1373:  * @return The number of bytes or -1 if it fails.
                   1374:  */
                   1375: int __axl_doc_get_flat_size_common (axlDoc * doc, axl_bool pretty_print, int tabular) 
                   1376: {
                   1377:        
                   1378:        int result;
                   1379:        axl_return_val_if_fail (doc, -1);
                   1380: 
                   1381:        /* count the xml header: 
                   1382:         *
                   1383:         * "<?xml version='1.0'" = 19 characters 
                   1384:         * " standalone='yes'"   = 17 characters
                   1385:         * " encoding='enc'"     = 12 characters + strlen (enc)
                   1386:         * " ?>"                 = 3  characters
                   1387:         *
                   1388:         * if pretty print add: "\r\n" +2 on windows
                   1389:         * and \n on unix.
                   1390:         */
                   1391:        result = 22;
                   1392: 
                   1393:        if (pretty_print)
                   1394: #ifdef __AXL_OS_WIN32__
                   1395:                result += 2;
                   1396: #else
                   1397:                result += 1;
                   1398: #endif
                   1399: 
                   1400:        if (doc->standalone)
                   1401:                result += 17;
                   1402:        
                   1403:        if (doc->encoding != NULL) {
                   1404:                result += 12 + strlen (doc->encoding);
                   1405:        }
                   1406:        
                   1407:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document header size=%d",
                   1408:                   result);
                   1409: 
                   1410:        /* now, count every node that the document have */
                   1411:        result += axl_node_get_flat_size (doc->rootNode, pretty_print, 0, tabular);
                   1412: 
                   1413:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "xml document body size=%d",
                   1414:                   result);
                   1415:        
                   1416:        /* return current result */
                   1417:        return result;
                   1418: }
                   1419: 
                   1420: /** 
                   1421:  * @internal
                   1422:  * Common implementation for the dumping functions.
                   1423:  */
                   1424: axl_bool __axl_doc_dump_common (axlDoc * doc, char ** content, int * size, axl_bool pretty_print, int tabular, axlError ** err)
                   1425: {
                   1426: 
                   1427:        char * result;
                   1428:        int    index;
                   1429: 
                   1430:        /* nullify before returning */
                   1431:        if (content)
                   1432:                *content = NULL;
                   1433:        if (size)
                   1434:                *size = 0;
                   1435: 
                   1436:        /* perform some envrironmental checks */
                   1437:        if (doc == NULL) {
                   1438:                axl_error_report (err, -1, "Received null doc reference to perform dump operation.");
                   1439:                return axl_false;
                   1440:        } else if (content == NULL) {
                   1441:                axl_error_report (err, -2, "Received null content reference to perform dump operation. To dump the content it is required a valid memory reference to place the content.");
                   1442:                return axl_false;
                   1443:        } else if (size == NULL) {
                   1444:                axl_error_report (err, -3, "Received null size reference to perform dump operation. To dump the content it is required a valid memory reference to report size");
                   1445:                return axl_false;
                   1446:        }
                   1447: 
                   1448:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting document size..");
                   1449: 
                   1450:        /* get the about of memory to allocate so the whole xml
                   1451:         * document fit in only one memory block */
                   1452:        (* size)    = __axl_doc_get_flat_size_common (doc, pretty_print, tabular);
                   1453:        (* content) = NULL;
                   1454: 
                   1455:        /* check returned size */
                   1456:        if ((* size) == -1) {
                   1457:                axl_error_report (err, -4, "Failed to perform dump operation, unable to calculate document size to perform dump.");
                   1458:                return axl_false;
                   1459:        }
                   1460: 
                   1461:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document dump size: %d", *size);
                   1462:        
                   1463:        /* allocate the memory block required */
                   1464:        result = axl_new (char, (*size) + 1);
                   1465: 
                   1466:        /* xml document header */
                   1467:        index = 0;
                   1468:        memcpy (result, "<?xml version='1.0' ", 20);
                   1469:        index = 20;
                   1470: 
                   1471:        /* encoding declaration */
                   1472:        if (doc->encoding) {
                   1473:                /* initial encoding declaration */
                   1474:                memcpy (result + index, "encoding='", 10);
                   1475:                index += 10;
                   1476: 
                   1477:                /* copy encoding content */
                   1478:                memcpy (result + index, doc->encoding, strlen (doc->encoding));
                   1479:                index += strlen (doc->encoding);
                   1480: 
                   1481:                /* encoding trailing */
                   1482:                memcpy (result + index, "' ", 2);
                   1483:                index += 2;
                   1484:        }
                   1485: 
                   1486:        /* standalone attribute */
                   1487:        if (doc->standalone) {
                   1488:                memcpy (result + index, "standalone='yes' ", 17); 
                   1489:                index += 17;
                   1490:        }
                   1491: 
                   1492:        /* header trailing */
                   1493:        memcpy (result + index, "?>", 2);
                   1494:        index += 2;
                   1495: 
                   1496:        if (pretty_print) {
                   1497: #ifdef __AXL_OS_WIN32__
                   1498:                memcpy (result + index, "\r\n", 2);
                   1499:                index += 2;
                   1500: #else
                   1501:                memcpy (result + index, "\n", 1);
                   1502:                index += 1;
                   1503: #endif
                   1504:        }
                   1505:        
                   1506:        /* dump node information */
                   1507:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "starting dump at: %d", index);
                   1508:        index    = axl_node_dump_at (doc->rootNode, result, index, pretty_print, 0, tabular);
                   1509: 
                   1510:        /* check dump size */
                   1511:        if (*size != index) {
                   1512:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "internal dump error, inconsitent size: calculated=%d != returned=%d",
                   1513:                           *size, index);
                   1514: 
                   1515:                axl_error_report (err, -5, "Internal dump error, inconsistent size: calculated=%d != returned=%d",
                   1516:                                  *size, index);
                   1517: 
                   1518:                /* free allocated result */
                   1519:                axl_free (result);
                   1520: 
                   1521:                *size    = -1;
                   1522:                *content = NULL;
                   1523: 
                   1524:                return axl_false;
                   1525:        }
                   1526: 
                   1527:        /* set results */
                   1528:        *content = result;
                   1529:        *size    = index;
                   1530:        
                   1531:        return axl_true;
                   1532: }
                   1533: /** 
                   1534:  * @brief Allows to get the xml representation for the provided \ref
                   1535:  * axlDoc reference.
                   1536:  *
                   1537:  * Given the \ref axlDoc reference, which represents a XML document,
                   1538:  * this function allows to get its stringify representation.
                   1539:  * 
                   1540:  * @param doc The \ref axlDoc to stringify
                   1541:  *
                   1542:  * @param content The reference where the result will be returned.
                   1543:  *
                   1544:  * @param size The reference where the document content size will be
                   1545:  * returned.
                   1546:  *
                   1547:  * @return The function returns \ref axl_true if the dump operation was
                   1548:  * performed. Otherwise \ref axl_false is returned.
                   1549:  */
                   1550: axl_bool      axl_doc_dump                     (axlDoc  * doc, 
                   1551:                                                char   ** content, 
                   1552:                                                int     * size)
                   1553: {
                   1554:        /* use common implementation */
                   1555:        return __axl_doc_dump_common (doc, content, size, axl_false, 0, NULL);
                   1556: }
                   1557: 
                   1558: 
                   1559: /** 
                   1560:  * @brief Allows to perform a dump operation like \ref axl_doc_dump,
                   1561:  * but making the output to be pretty printed.
                   1562:  * 
                   1563:  * @param doc The \ref axlDoc reference to be dumped.
                   1564:  *
                   1565:  * @param content The reference that will hold the dumped information.
                   1566:  *
                   1567:  * @param size Result size for the dumped information.
                   1568:  *
                   1569:  * @param tabular The tabular size basic unit used for level
                   1570:  * tabulation. An appropiate value could be 4.
                   1571:  * 
                   1572:  * @return \ref axl_true if the document was dumped, \ref axl_false if
                   1573:  * something has failed.
                   1574:  */
                   1575: axl_bool      axl_doc_dump_pretty              (axlDoc  * doc,
                   1576:                                                char   ** content,
                   1577:                                                int     * size,
                   1578:                                                int       tabular)
                   1579: {
                   1580:        /* use common implementation */
                   1581:        return __axl_doc_dump_common (doc, content, size, axl_true, tabular, NULL);
                   1582: }
                   1583: 
                   1584: /** 
                   1585:  * @brief Allows to dump a xml document directly to the file located
                   1586:  * at the file path.
                   1587:  *
                   1588:  * This function saves you the round trip to declare variables to hold
                   1589:  * the memory, open a file, dump the content and properly close the
                   1590:  * output file. The function works the same as \ref axl_doc_dump but
                   1591:  * doing the extra job to transfer the xml document into a file.
                   1592:  *
                   1593:  * See also \ref axl_doc_dump_pretty_to_file to get a version dumps
                   1594:  * the content doing some pretty printing operations.
                   1595:  * 
                   1596:  * @param doc The document to be dumped into a file.
                   1597:  *
                   1598:  * @param file_path The file path where the output will be placed. The
                   1599:  * function will require to have access rights to the file (or to
                   1600:  * create a new file if it doesnt exists). The default behaviour is to
                   1601:  * overwrite the file found if exists. So, if you don't want to get
                   1602:  * content overwrited, you must provide the enough code to avoid such
                   1603:  * situations prior calling to this function.
                   1604:  * 
                   1605:  * @return \ref axl_true if the dump operation was ok, otherwisde \ref
                   1606:  * axl_false is returned.
                   1607:  */
                   1608: axl_bool      axl_doc_dump_to_file             (axlDoc      * doc,
                   1609:                                                const char  * file_path)
                   1610: {
                   1611:        char * content = NULL;
                   1612:        int    size    = -1;
                   1613:        int    written = -1;
                   1614:        FILE * fd      = NULL;
                   1615: 
                   1616:        /* dump content and check result */
                   1617:        if (! __axl_doc_dump_common (doc, &content, &size, axl_false, 0, NULL)) {
                   1618:                /* no dump operation done */
                   1619:                return axl_false;
                   1620:        }
                   1621: 
                   1622:        /* open the file and check */
                   1623: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   1624:        if (fopen_s (&fd, file_path, "w") != 0) {
                   1625: #else
                   1626:        if ((fd = fopen (file_path, "w")) == NULL) {
                   1627: #endif
                   1628:                /* failed to open the file to dump the content */
                   1629:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump document due to an error on fopen() call.");
                   1630:                axl_free (content);
                   1631: 
                   1632:                return axl_false;
                   1633:        }
                   1634: 
                   1635:        /* dump the content */
                   1636:        written = fwrite (content, 1, size, fd);
                   1637: 
                   1638:        /* free the content */
                   1639:        axl_free (content);
                   1640: 
                   1641:        /* close file */
                   1642:        fclose (fd);
                   1643: 
                   1644:        /* return if we have failed to dump all the content to the
                   1645:         * file or not. */
                   1646:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   1647:                   (written == size) ? "OK" : "FAILED", 
                   1648:                   written, size);
                   1649:                   
                   1650:        return (written == size);
                   1651: }
                   1652: 
                   1653: /** 
                   1654:  * @brief Allows to dump a xml document directly to the file located
                   1655:  * at the file path, doing pretty printing operations.
                   1656:  *
                   1657:  * This function saves you the round trip to declare variables to hold
                   1658:  * the memory, open a file, dump the content and properly close the
                   1659:  * output file. The function works the same as \ref axl_doc_dump but
                   1660:  * doing the extra job to transfer the xml document into a file.
                   1661:  *
                   1662:  * See also \ref axl_doc_dump_to_file to get a version dumps the
                   1663:  * content without doing pretty printing operations.
                   1664:  * 
                   1665:  * @param doc The document to be dumped into a file.
                   1666:  *
                   1667:  * @param file_path The file path where the output will be placed. The
                   1668:  * function will require to have access rights to the file (or to
                   1669:  * create a new file if it doesnt exists). The default behaviour is to
                   1670:  * overwrite the file found if exists. So, if you don't want to get
                   1671:  * content overwrited, you must provide the enough code to avoid such
                   1672:  * situations prior calling to this function.
                   1673:  * 
                   1674:  * @param tabular The amount of white spaces to introduce as tabular
                   1675:  * for each level found inside the xml.
                   1676:  * 
                   1677:  * @return \ref axl_true if the dump operation was ok, otherwisde \ref
                   1678:  * axl_false is returned.
                   1679:  */
                   1680: axl_bool      axl_doc_dump_pretty_to_file      (axlDoc      * doc,
                   1681:                                                const char  * file_path,
                   1682:                                                int           tabular)
                   1683: {
                   1684:        char     * content = NULL;
                   1685:        int        size    = -1;
                   1686:        int        written = -1;
                   1687:        FILE     * fd      = NULL;
                   1688:        axlError * err     = NULL;
                   1689: 
                   1690:        /* dump content and check result */
                   1691:        if (! __axl_doc_dump_common (doc, &content, &size, axl_true, tabular, &err)) {
                   1692:                /* no dump operation done */
                   1693:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to perform dump operation. Internal error found: %s",
                   1694:                           axl_error_get (err));
                   1695:                axl_error_free (err);
                   1696:                return axl_false;
                   1697:        } /* end if */
                   1698: 
                   1699:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document dumped, now transfer that content to a file");
                   1700: 
                   1701:        /* open the file and check */
                   1702: #if defined(AXL_OS_WIN32) && ! defined(__GNUC__)
                   1703:        if (fopen_s (&fd, file_path, "w") != 0) {
                   1704: #else
                   1705:        if ((fd = fopen (file_path, "w")) == NULL) {
                   1706: #endif
                   1707:                /* failed to open the file to dump the content */
                   1708:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "failed to dump document due to an error on fopen() call.");
                   1709:                axl_free (content);
                   1710: 
                   1711:                return axl_false;
                   1712:        }
                   1713: 
                   1714:        /* dump the content */
                   1715:        written = fwrite (content, 1, size, fd);
                   1716: 
                   1717:        /* free the content */
                   1718:        axl_free (content);
                   1719: 
                   1720:        /* close file */
                   1721:        fclose (fd);
                   1722: 
                   1723:        /* return if we have failed to dump all the content to the
                   1724:         * file or not. */
                   1725:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "returning that the dump was: %s (written:%d == size:%d)", 
                   1726:                   (written == size) ? "OK" : "FAILED", 
                   1727:                   written, size);
                   1728:        return (written == size);
                   1729: }
                   1730: 
                   1731: /** 
                   1732:  * @brief Allows to get how much will take the \ref axlDoc instance
                   1733:  * represented as an XML document in an storage device (like memory).
                   1734:  *
                   1735:  * @param doc The \ref axlDoc reference that is being requested to return its size.
                   1736:  * 
                   1737:  * @return The size the \ref axlDoc will represent, in a
                   1738:  * octect-counting, or -1 if fails. The function will only fail if the
                   1739:  * provided reference is NULL.
                   1740:  */
                   1741: int axl_doc_get_flat_size (axlDoc * doc)
                   1742: {
                   1743:        /* use common implementation */
                   1744:        return __axl_doc_get_flat_size_common (doc, axl_false, 0);
                   1745: }
                   1746: 
                   1747: 
                   1748: /** 
                   1749:  * @brief Parse an XML entity that is hold inside the memory pointed
                   1750:  * by <b>entity</b> and limited by <b>entity_size</b>.
                   1751:  *
                   1752:  * The function parses the XML document inside the memory hold inside
                   1753:  * the given reference. The function returns an XML document,
                   1754:  * represented by \ref axlDoc.
                   1755:  *
                   1756:  * The function, optionall, could report error found inside the given
                   1757:  * \ref axlError variable. In the case the function returns a NULL
                   1758:  * value, this variable is filled containing the a textual diagnostic
                   1759:  * error to be showed to the user interface and an error code.
                   1760:  *
                   1761:  * Here is an example:
                   1762:  * \code
                   1763:  * // axl document representation 
                   1764:  * axlDoc   * doc;
                   1765:  * axlError * error;
                   1766:  *     
                   1767:  *
                   1768:  * // parse the given string 
                   1769:  * doc = axl_doc_parse ("<?xml version='1.0' ?><axldoc />", 32, &error);
                   1770:  * if (doc == NULL) {
                   1771:  *      printf ("Error found: %s\n", axl_error_get (error));
                   1772:  *      axl_error_free (error);
                   1773:  *      return axl_false;
                   1774:  * }
                   1775:  *
                   1776:  * // release document parsed 
                   1777:  * axl_doc_free (doc); 
                   1778:  * \endcode
                   1779:  * 
                   1780:  * @param entity The XML document to load.
                   1781:  *
                   1782:  * @param entity_size The XML document size to load. If a <b>-1</b> is
                   1783:  * provided, strlen function is used to figure out current document
                   1784:  * size. This is not recomended while using xml documents that include
                   1785:  * binary data, that maybe comes inside the CDATA section or because
                   1786:  * an utf caracter used that includes the \\0 inside its value.
                   1787:  *
                   1788:  * @param error Optional \ref axlError reference that will be used to
                   1789:  * report errors found while processing xml into the \ref axlDoc
                   1790:  * instance.
                   1791:  * 
                   1792:  * @return A newly allocated Axl Document, that must be deallocated
                   1793:  * using \ref axl_doc_free, when no longer needed. The function could
                   1794:  * return NULL if the document is not loaded properly.
                   1795:  *
                   1796:  * In the case an error is found while procesing the document, error
                   1797:  * variable will be filled, if defined. -1 will be returned is
                   1798:  * received parameter are wrong. -2 will be returned if there some
                   1799:  * error is found while processing the document.
                   1800:  */
                   1801: axlDoc * axl_doc_parse (const char * entity, int entity_size, axlError ** error)
                   1802: {
                   1803:        return __axl_doc_parse_common (entity, entity_size, NULL, -1, error);
                   1804: }
                   1805: 
                   1806: /** 
                   1807:  * @internal
                   1808:  * 
                   1809:  * Allows to get current file size, in bytes, of the provided file
                   1810:  * located at the given file path.
                   1811:  */
                   1812: int __axl_doc_get_file_size (char * file_path)
                   1813: {
                   1814:        struct stat buf;
                   1815: 
                   1816:        axl_return_val_if_fail (file_path, -1);
                   1817:        
                   1818:        /* clear the memory hold */
                   1819:        memset (&buf, 0, sizeof (struct stat));
                   1820: 
                   1821:        /* return current file size */
                   1822:        if (stat ((const char *) file_path, &buf) < 0)
                   1823:                return -1;
                   1824:        
                   1825:        /* return the file size */
                   1826:        return buf.st_size;
                   1827:        
                   1828: }
                   1829: 
                   1830: /** 
                   1831:  * @brief Allows to parse an xml document from the given file path
                   1832:  * location.
                   1833:  *
                   1834:  * This function works the same way like \ref axl_doc_parse and \ref
                   1835:  * axl_doc_parse_strings, but using as an input, the selected file
                   1836:  * provided by the path. In fact, all this function, use the same xml
                   1837:  * parse engine. The advantage of this function is that it is more
                   1838:  * efficient while reading huge xml files. 
                   1839:  *
                   1840:  * Here is an example:
                   1841:  * \code
                   1842:  * axlDoc   * doc = NULL;
                   1843:  * axlError * error = NULL;
                   1844:  *
                   1845:  * // parse the provide file
                   1846:  * doc = axl_doc_parse_from_file ("test.xml", &error);
                   1847:  * if (doc == NULL) {
                   1848:  *    // check error found
                   1849:  *    printf ("ERROR: (code: %d) %s\n",
                   1850:  *            axl_error_get_code (error),
                   1851:  *            axl_error_get (error));
                   1852:  *    axl_error_free (error);
                   1853:  *    return -1;
                   1854:  * }
                   1855:  *
                   1856:  * // do some stuff with the readed document
                   1857:  * 
                   1858:  * // release it once no longer needed
                   1859:  * axl_doc_free (doc);
                   1860:  * \endcode
                   1861:  * 
                   1862:  * @param file_path The file path to report.
                   1863:  *
                   1864:  * @param error The \ref axlError where errors found will be reported.
                   1865:  * 
                   1866:  * @return 
                   1867:  */
                   1868: axlDoc  * axl_doc_parse_from_file          (const char * file_path,
                   1869:                                            axlError  ** error)
                   1870: {
                   1871:        return __axl_doc_parse_common (NULL, -1, file_path, -1, error);
                   1872: }
                   1873: 
                   1874: 
                   1875: /** 
                   1876:  * @brief Allows to parse an xml document that is provided as a set of
                   1877:  * strings ended by a NULL reference.
                   1878:  *
                   1879:  * This function works the same way like \ref axl_doc_parse function,
                   1880:  * but allowing to provide a set of strings. Here is an example:
                   1881:  * 
                   1882:  * \code
                   1883:  * // a document reference
                   1884:  * axlDoc   * doc;
                   1885:  *
                   1886:  * // note that the error is optional, and, if provided, it is not
                   1887:  * // required to initialize it.
                   1888:  * axlError * error;
                   1889:  * 
                   1890:  * // parse the following set of strings
                   1891:  * doc = axl_doc_parse_strings (&error, 
                   1892:  *                              "<?xml version='1.0' standalone='yes' ?>",
                   1893:  *                              "<complex>",
                   1894:  *                              "  <data>",
                   1895:  *                              "     <row>",
                   1896:  *                              "       <td>",
                   1897:  *                              "          <value attr='10'/>
                   1898:  *                              "       </td>",
                   1899:  *                              "     </row>",
                   1900:  *                              "  </data>",
                   1901:  *                              "</complex>",
                   1902:  *                              NULL); // last null reference 
                   1903:  * // check for an error
                   1904:  * if (doc == NULL) {
                   1905:  *      printf ("There was an error while parsing the document: (code: %d) %s\n",
                   1906:  *              axl_error_get_code (error), axl_error_get (error));
                   1907:  *      axl_error_free (error);
                   1908:  * }
                   1909:  * \endcode
                   1910:  * 
                   1911:  * @param error An optional \ref axlError reference where a textual
                   1912:  * diagnostic will be provided.
                   1913:  * 
                   1914:  * @return A newly created \ref axlDoc reference that must be
                   1915:  * deallocated by using \ref axl_doc_free when no longer needed.
                   1916:  */
                   1917: axlDoc  * axl_doc_parse_strings            (axlError ** error,
                   1918:                                            ...)
                   1919: {
                   1920:        axlDoc   * doc;
                   1921:        va_list    args;
                   1922:        char     * string     = NULL;
                   1923:        char     * stream     = NULL;
                   1924:        char     * stream_aux = NULL;
                   1925:        
                   1926:        /* check incoming data */
                   1927:        axl_return_val_if_fail (error, NULL);
                   1928:        
                   1929:        /* open the stdargs */
                   1930:        va_start (args, error);
                   1931:        
                   1932:        while ((string = va_arg (args, char *)) != NULL) {
                   1933:                stream_aux = stream;
                   1934:                stream = axl_stream_concat (stream, string);
                   1935:                if (stream_aux != NULL) {
                   1936:                        axl_free (stream_aux);
                   1937:                        stream_aux = NULL;
                   1938:                }
                   1939:        }
                   1940: 
                   1941:        /* close the stdargs */
                   1942:        va_end (args);
                   1943: 
                   1944:        /* check that we have received, at least, an string
                   1945:         * parseable */
                   1946:        if (stream == NULL)
                   1947:                return NULL;
                   1948: 
                   1949:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "string to parse: %s", stream);
                   1950: 
                   1951:        /* parse the string */
                   1952:        doc = axl_doc_parse (stream, -1, error);
                   1953: 
                   1954:        /* free the stream */
                   1955:        axl_free (stream);
                   1956: 
                   1957:        return doc;
                   1958: }
                   1959: 
                   1960: /** 
                   1961:  * @internal 
                   1962:  * 
                   1963:  * Internal support function which checks the provided child and its
                   1964:  * childs are equal.
                   1965:  */
                   1966: axl_bool __axl_doc_are_equal (axlNode * node, axlNode * node2, axl_bool trimmed, axlError ** error)
                   1967: {
                   1968:        int       iterator;
                   1969:        int       length;
                   1970:        int       length2;
                   1971: 
                   1972:        axlItem * child;
                   1973:        axlItem * child2;
                   1974:        
                   1975:        /* check if parent nodes are equal */
                   1976:        if (! axl_node_are_equal (node, node2))
                   1977:                return axl_false;
                   1978: 
                   1979:        /* iterate over all childs inside the node */
                   1980:        iterator = 0;
                   1981:        length   = axl_node_get_child_num (node);
                   1982:        length2  = axl_node_get_child_num (node2);
                   1983: 
                   1984:        if (length != length2) {
                   1985:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child number differs, documents aren't equal");
                   1986:                axl_error_report (error, -1,  "child number differs, documents aren't equal");
                   1987:                return axl_false;
                   1988:        }
                   1989: 
                   1990:        /* get the first item inside the node */
                   1991:        child  = axl_item_get_first_child (node);
                   1992:        child2 = axl_item_get_first_child (node2);
                   1993: 
                   1994:        /* for each item child found in both nodes */
                   1995:        while (child != NULL && child2 != NULL) {
                   1996:                
                   1997:                if (child == NULL)  {
                   1998:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child from the first document is null..");
                   1999:                        axl_error_report (error, -1, "child from the first document is null..");
                   2000:                }
                   2001: 
                   2002:                if (child2 == NULL) {
                   2003:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "child from the second document is null..");
                   2004:                        axl_error_report (error, -1,  "child from the second document is null..");
                   2005:                }
                   2006: 
                   2007:                /* check if these nodes are also equal */
                   2008:                if (! axl_item_are_equal_full (child, child2, trimmed, error)) {
                   2009:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "items  aren't equal, document is not equal");
                   2010:                        return axl_false;
                   2011:                }
                   2012: 
                   2013:                /* check its childs in the case the axl item is
                   2014:                 * representing an item node */
                   2015:                if (axl_item_get_type (child) == ITEM_NODE) {
                   2016:                        /* get a reference */
                   2017:                        node  = axl_item_get_data (child);
                   2018:                        node2 = axl_item_get_data (child2);
                   2019: 
                   2020:                        if (! __axl_doc_are_equal (node, node2, trimmed, error)) {
                   2021:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "nodes <%s> and <%s> aren't equal, document is not equal", 
                   2022:                                           axl_node_get_name (node), axl_node_get_name (node2));
                   2023:                                return axl_false;
                   2024:                        } /* end if */
                   2025:                }
                   2026: 
                   2027:                /* get a referece to the next childs to check */
                   2028:                child  = axl_item_get_next (child);
                   2029:                child2 = axl_item_get_next (child2);
                   2030:                
                   2031:        } /* end while */
                   2032: 
                   2033:        /* the nodes recieved are equal */
                   2034:        return (child == NULL && child2 == NULL);
                   2035: }
                   2036: 
                   2037: /** 
                   2038:  * @internal Common implementation for equal documents.
                   2039:  */
                   2040: axl_bool      axl_doc_are_equal_common (axlDoc    * doc,
                   2041:                                        axlDoc    * doc2,
                   2042:                                        axl_bool    trimmed,
                   2043:                                        axlError ** error)
                   2044: {
                   2045:        axlNode * node;
                   2046:        axlNode * node2;
                   2047: 
                   2048:        /* check first reference */
                   2049:        if (doc == NULL) {
                   2050:                axl_error_report (error, -1, "Documents differs because first document reference is null");
                   2051:                return axl_false;
                   2052:        }
                   2053:        /* check second reference */
                   2054:        if (doc2 == NULL) {
                   2055:                axl_error_report (error, -1, "Documents differs because second document reference is null");
                   2056:                return axl_false;
                   2057:        }
                   2058: 
                   2059:        /* first, check the document root */
                   2060:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking that both documents are equal");
                   2061: 
                   2062:        node  = axl_doc_get_root (doc);
                   2063:        if (node == NULL) {
                   2064:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document(a) doesn't have document root ..");
                   2065:        }
                   2066:        node2 = axl_doc_get_root (doc2);
                   2067:        if (node2 == NULL) {
                   2068:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "document(b) doesn't have document root ..");
                   2069:        }
                   2070: 
                   2071:        /* call to common implemenation, activating triming */
                   2072:        return __axl_doc_are_equal (node, node2, trimmed, error);
                   2073: }
                   2074: 
                   2075: /** 
                   2076:  * @brief Allows to perform a document equal check against order,
                   2077:  * relaxing the checking done to contet found inside nodes.
                   2078:  *
                   2079:  * This function works the same as \ref axl_doc_are_equal but
                   2080:  * considering that two content are equal no matter which is the
                   2081:  * number of white spaces (in the W3C, ' ', \\t, \\r and \\n) are
                   2082:  * found starting and ending the content.
                   2083:  *
                   2084:  * Under this approach the both document aren't exactly the same, but
                   2085:  * usually, white spaces found starting and ending content have no
                   2086:  * meaning for the application processing xml. In the case you want a
                   2087:  * fully equal document checking you must \ref axl_doc_are_equal
                   2088:  *
                   2089:  * @param doc The document to check.
                   2090:  * @param doc2 The second document to check
                   2091:  * 
                   2092:  * @return \ref axl_true if both documents are equal in the sense
                   2093:  * described, otherwise \ref axl_false is returned.
                   2094:  */
                   2095: axl_bool      axl_doc_are_equal_trimmed        (axlDoc * doc,
                   2096:                                                axlDoc * doc2)
                   2097: {
                   2098:        /* call to common implemenation, activating triming */
                   2099:        return axl_doc_are_equal_common (doc, doc2, axl_true, NULL);
                   2100: }
                   2101: 
                   2102: /** 
                   2103:  * @brief Allows to check if the provided two references represents
                   2104:  * equivalent xml documents.
                   2105:  *
                   2106:  * There is an alternative document checking function (\ref
                   2107:  * axl_doc_are_equal_trimmed) which considered that content found
                   2108:  * inside a xml node is equal if they share the same information
                   2109:  * without considering white spaces found starting and ending both
                   2110:  * elements being checked.
                   2111:  *
                   2112:  * This function considers that two documents are equal only and only
                   2113:  * if all nodes, attributes and content found is exactly, byte by
                   2114:  * byte, as found in the other document.
                   2115:  * 
                   2116:  * @param doc The first XML document to check.
                   2117:  * @param doc2 The second XML document to check.
                   2118:  * 
                   2119:  * @return axl_true if both documents represents the same document,
                   2120:  * axl_false if not.
                   2121:  */
                   2122: axl_bool      axl_doc_are_equal                (axlDoc * doc, 
                   2123:                                                axlDoc * doc2)
                   2124: {
                   2125:        /* call to common implemenation, activating triming */
                   2126:        return axl_doc_are_equal_common (doc, doc2, axl_true, NULL);
                   2127: }
                   2128: 
                   2129: /** 
                   2130:  * @brief Allows to check if the provided two references represents
                   2131:  * equivalent xml documents.
                   2132:  *
                   2133:  * There is an alternative document checking function (\ref
                   2134:  * axl_doc_are_equal_trimmed) which considered that content found
                   2135:  * inside a xml node is equal if they share the same information
                   2136:  * without considering white spaces found starting and ending both
                   2137:  * elements being checked.
                   2138:  *
                   2139:  * This function considers that two documents are equal only and only
                   2140:  * if all nodes, attributes and content found is exactly, byte by
                   2141:  * byte, as found in the other document.
                   2142:  * 
                   2143:  * @param doc The first XML document to check.
                   2144:  *
                   2145:  * @param doc2 The second XML document to check.
                   2146:  *
                   2147:  * @param trimmed Allows to configure if node content must be trimmed
                   2148:  * before checking them (\ref axl_doc_are_equal_trimmed).
                   2149:  *
                   2150:  * @param error An optional reference to an \ref axlError node where
                   2151:  * difference information will be reported.
                   2152:  * 
                   2153:  * @return axl_true if both documents represents the same document,
                   2154:  * axl_false if not.
                   2155:  */
                   2156: axl_bool      axl_doc_are_equal_full           (axlDoc    * doc, 
                   2157:                                                axlDoc    * doc2,
                   2158:                                                axl_bool    trimmed,
                   2159:                                                axlError ** error)
                   2160: {
                   2161:        /* call to common implemenation, activating triming */
                   2162:        return axl_doc_are_equal_common (doc, doc2, trimmed, error);
                   2163: }
                   2164: 
                   2165: 
                   2166: 
                   2167: 
                   2168: /** 
                   2169:  * @brief Allows to get current root node for the given xml document,
                   2170:  * represented by the \ref axlDoc instance.
                   2171:  *
                   2172:  * Every XML document has a very first node, which enclose all childs
                   2173:  * found inside the document, that is called the root node. This xml
                   2174:  * node, 
                   2175:  *
                   2176:  * This function couldn't return NULL because every well opened xml
                   2177:  * document, always have a root node. However, the function could
                   2178:  * return a NULL value if the document received is a null reference.
                   2179:  * 
                   2180:  * @param doc The xml document (\ref axlDoc) where the root node will
                   2181:  * be returned. 
                   2182:  * 
                   2183:  * @return The root node (\ref axlNode) or NULL if fails.
                   2184:  */
                   2185: axlNode * axl_doc_get_root                 (axlDoc * doc)
                   2186: {
                   2187:        axl_return_val_if_fail (doc, NULL);
                   2188:        
                   2189:        /* return current root node */
                   2190:        return doc->rootNode;
                   2191: }
                   2192: 
                   2193: /** 
                   2194:  * @internal
                   2195:  *
                   2196:  * @brief An always return 1 to make the list to store elements append
                   2197:  * at the end.
                   2198:  */
                   2199: int __axl_doc_get_are_equal (axlPointer a, axlPointer b)
                   2200: {
                   2201:        return 1;
                   2202: }
                   2203: 
                   2204: /** 
                   2205:  * @brief Allows to get a particular node (or list of nodes) that are
                   2206:  * located at a selected path.
                   2207:  *
                   2208:  * Providing a path, the function lookups for nodes stored on the
                   2209:  * selected location inside the provided document. The path provided
                   2210:  * doesn't follow the XPath extension. 
                   2211:  *
                   2212:  * Taking as a reference for the xml to be explained on the following
                   2213:  * rules:
                   2214:  * \code
                   2215:  * <complex>
                   2216:  *     <data>
                   2217:  *       <node>
                   2218:  *          <row>10</row>
                   2219:  *       </node>
                   2220:  *     </data>
                   2221:  * </complex>
                   2222:  * \endcode
                   2223:  *
                   2224:  *
                   2225:  * Here is how the path works:
                   2226:  * 
                   2227:  * - If provided a "/", the root node is returned. This is same than
                   2228:  * provided the root node name, like "/complex", when it is expected
                   2229:  * to find as root node &lt;complex>. However, providing a particular
                   2230:  * node to search allows to get ensure that the root node is the one
                   2231:  * looked up.
                   2232:  *
                   2233:  * - To select nodes inside the first root node, in a generic way,
                   2234:  * without providing details about the root node name, you could use
                   2235:  * "//\*". This will provide all nodes that are found inside the root
                   2236:  * node, whatever it is called. If it is required to get all nodes,
                   2237:  * inside the root node, ensuring that the root one is called
                   2238:  * "complex" you should use: "/complex/\*"
                   2239:  *
                   2240:  * - If it is required to get a selected node inside the root node,
                   2241:  * that is called in a particular way you can use: //data. Again, if
                   2242:  * it is required to ensure that a particular node exists, from the
                   2243:  * top level down the leaf node, it will required to write something
                   2244:  * like: "/complex/data". 
                   2245:  *
                   2246:  * - Remember that is totally different to query for "/complex/data"
                   2247:  * than "/complex/data/\*". The first one, returns the node, or nodes,
                   2248:  * called <b>data</b> that are inside the root node called
                   2249:  * <b>complex</b>, while the second one says: return all nodes inside
                   2250:  * the node <b>data</b> that is inside the root node called
                   2251:  * <b>complex</b>
                   2252:  *
                   2253:  * Finally, keep in mind that this function only returns nodes. To get
                   2254:  * node content, attributes or anything else, you'll have to get the
                   2255:  * node first and then operate with it.
                   2256:  *
                   2257:  *
                   2258:  *
                   2259:  * @param doc The \ref axlDoc reference where the lookup will be
                   2260:  * performed.
                   2261:  *
                   2262:  * @param path_to A path to the node (nodes) that are inside the path
                   2263:  * especifyied.
                   2264:  * 
                   2265:  * @return A list of nodes (\ref axlNode) if the case something is
                   2266:  * found or NULL if fails to find something at the given path. If the
                   2267:  * path is right but no node match with it or there is no node, the
                   2268:  * function will return NULL reference rather a list with no
                   2269:  * nodes. Returned value must be deallocated by using \ref
                   2270:  * axl_list_free.
                   2271:  */
                   2272: axlList * axl_doc_get_list                  (axlDoc * doc, const char * path_to)
                   2273: {
                   2274:        axlList  * nodes;
                   2275:        axlNode  * node     = NULL;
                   2276:        int        iterator = 0;
                   2277:        char    ** paths    = 0;
                   2278:        
                   2279: 
                   2280:        axl_return_val_if_fail (doc, NULL);
                   2281:        axl_return_val_if_fail (path_to, NULL);
                   2282:        axl_return_val_if_fail (path_to[0] == '/', NULL);
                   2283: 
                   2284:        /* create the axl list */
                   2285:        nodes = axl_list_new (__axl_doc_get_are_equal, NULL);
                   2286:        
                   2287:        /* split paths */
                   2288:        paths = axl_stream_split (path_to, 1, "/");
                   2289:        axl_return_val_if_fail (paths, nodes);
                   2290: 
                   2291:        /* get a reference to the root node */
                   2292:        node = doc->rootNode;
                   2293: 
                   2294:        /* basic case, check for the root node */
                   2295:        if (strlen (paths[1]) != 0) {
                   2296:                /* check the node is the one requested */
                   2297:                if (! NODE_CMP_NAME (node, paths[1])) {
                   2298:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "requested root node = %s wasn't found, current root %s", paths[1],
                   2299:                                   axl_node_get_name (doc->rootNode));
                   2300:                        axl_list_free (nodes);
                   2301:                        axl_stream_freev (paths);
                   2302:                        return NULL;
                   2303:                }
                   2304:        }
                   2305: 
                   2306:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found node: %s for path=%s", paths[1], path_to);
                   2307: 
                   2308:        /* now the general case */
                   2309:        iterator = 2;
                   2310:        while ((paths[iterator] != NULL) && (strlen (paths[iterator]) > 0)) {
                   2311:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking path item %s", paths[iterator]);
                   2312:                
                   2313:                /* check that the last path is used */
                   2314:                if (axl_cmp (paths[iterator], "*") && 
                   2315:                    (axl_stream_strv_num (paths) != iterator + 1)) {
                   2316:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using the '*' at that path different from the last one.", paths[iterator]);
                   2317:                        axl_list_free (nodes);
                   2318:                        axl_stream_freev (paths);
                   2319:                        return NULL;
                   2320:                }
                   2321: 
                   2322:                /* get a reference to the node searched */
                   2323:                node = axl_node_get_child_called (node, paths[iterator]);
                   2324:                if (node == NULL) {
                   2325:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the node located at %s wasn't found.", path_to);
                   2326: 
                   2327:                        axl_list_free (nodes);
                   2328:                        axl_stream_freev (paths);
                   2329:                        return NULL;
                   2330:                }
                   2331:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found node: %s", paths[iterator]);
                   2332: 
                   2333:                /* update iterator value */
                   2334:                iterator++;
                   2335:        }
                   2336: 
                   2337:        /* add the node found */
                   2338:        axl_list_add (nodes, node);
                   2339: 
                   2340:        /* free paths */
                   2341:        axl_stream_freev (paths);
                   2342: 
                   2343:        /* return the node found */
                   2344:        return nodes;
                   2345: }
                   2346: 
                   2347: /** 
                   2348:  * @brief Allows to return only one node for the selected path.
                   2349:  *
                   2350:  * This function works the same way like \ref axl_doc_get_list but
                   2351:  * extracting the first node reference found inside the list returned
                   2352:  * by the previous function, and returning it.
                   2353:  *
                   2354:  * Many times, a path is selected because it is know that under that
                   2355:  * location couldn't be more than one element. However, using \ref
                   2356:  * axl_doc_get_list function makes this task really anoying because
                   2357:  * you have to get the list, extract the node, from the list, and
                   2358:  * releasing the list reference to actually get access to the node
                   2359:  * looked up.
                   2360:  *
                   2361:  * This function allows you to get access to the node stored on the
                   2362:  * selected location, and, if a path that provides several nodes is
                   2363:  * returned, only the first node found on that list is returned.
                   2364:  * 
                   2365:  * @param doc The \ref axlDoc document where the node will be returned.
                   2366:  * @param path_to A path to the node to get.
                   2367:  * 
                   2368:  * @return A reference to a \ref axlNode instace, or NULL if
                   2369:  * fails. Returned reference must not be deallocated.
                   2370:  */
                   2371: axlNode * axl_doc_get                      (axlDoc * doc, const char * path_to)
                   2372: {
                   2373:        axlList * list = NULL;
                   2374:        axlNode * node = NULL;
                   2375:        
                   2376:        axl_return_val_if_fail (doc, NULL);
                   2377:        axl_return_val_if_fail (path_to, NULL);
                   2378: 
                   2379:        /* get the list of nodes */
                   2380:        list = axl_doc_get_list (doc, path_to);
                   2381:        if (list == NULL)
                   2382:                return NULL;
                   2383:        
                   2384:        /* get the node requested */
                   2385:        if (axl_list_length (list) > 0)
                   2386:                node = axl_list_get_nth (list, 0);
                   2387: 
                   2388:        axl_list_free (list);
                   2389:        return node;
                   2390:        
                   2391: }
                   2392: 
                   2393: /** 
                   2394:  * @brief Allows to get the node content for the final node provided
                   2395:  * by the path.
                   2396:  * 
                   2397:  * @param doc The (\ref axlDoc) xml document where the content will be
                   2398:  * looked up.
                   2399:  *
                   2400:  * @param path_to Path to the node where the content will be returned.
                   2401:  *
                   2402:  * @param content_size An optional reference to a variable to store
                   2403:  * the size of the content returned. If the function receives NULL,
                   2404:  * the content size will not be returned.
                   2405:  * 
                   2406:  * @return A reference to the content that the node have or NULL if
                   2407:  * fails. The function could fail either because the node doesn't have
                   2408:  * content or because the node identified by the path doesn't
                   2409:  * exist. The result returned must not be deallocated.
                   2410:  */
                   2411: const char    * axl_doc_get_content_at     (axlDoc     * doc,
                   2412:                                            const char * path_to,
                   2413:                                            int        * content_size)
                   2414: {
                   2415: 
                   2416:        axlNode * node;
                   2417: 
                   2418:        /* get the node reference */
                   2419:        node = axl_doc_get (doc, path_to);
                   2420:        axl_return_val_if_fail (node, NULL);
                   2421: 
                   2422:        /* return the content requested */
                   2423:        return axl_node_get_content (node, content_size);
                   2424:        
                   2425: }
                   2426: 
                   2427: /** 
                   2428:  * @brief Gets current axl Document encoding.
                   2429:  * 
                   2430:  * @param doc The document where the encoding will be retrieved.
                   2431:  * 
                   2432:  * @return A valid \ref axlDoc reference. NULL is returned in the case
                   2433:  * a NULL \ref axlDoc reference is received. The value returned by
                   2434:  * this function must not be deallocated.
                   2435:  */
                   2436: const char * axl_doc_get_encoding (axlDoc * doc)
                   2437: {
                   2438:        /* check parameter received */
                   2439:        axl_return_val_if_fail (doc, NULL);
                   2440:        
                   2441:        return (doc->encoding != NULL) ? doc->encoding : "";
                   2442: }
                   2443: 
                   2444: /** 
                   2445:  * @brief Allows to get current standalone configuration for the given
                   2446:  * axlDoc document.
                   2447:  * 
                   2448:  * @param doc The \ref axlDoc document where the standalone value will
                   2449:  * be retreived.
                   2450:  * 
                   2451:  * @return \ref axl_true if the standalone configuration, found inside
                   2452:  * the xml header is set to AXL_TRUE. Otherwise \ref axl_false is
                   2453:  * returned. Keep in mind that the function will return an \ref
                   2454:  * axl_false value if a null reference is received.
                   2455:  */
                   2456: axl_bool     axl_doc_get_standalone (axlDoc * doc)
                   2457: {
                   2458:        axl_return_val_if_fail (doc, axl_false);
                   2459: 
                   2460:        /* return current configuration */
                   2461:        return doc->standalone;
                   2462: }
                   2463: 
                   2464: /** 
                   2465:  * @brief Allows to configure the document root for the given \ref
                   2466:  * axlDoc instance.
                   2467:  *
                   2468:  * Every xml document has a xml node root. This is the first node,
                   2469:  * that holds all childs. This function allows to configure that xml
                   2470:  * document root. See also \ref axl_doc_get_root.
                   2471:  *
                   2472:  * Remember that previous document root will not be deallocated so,
                   2473:  * the user space must take care about previous reference.
                   2474:  *
                   2475:  * @param doc The \ref axlDoc where the document root will be
                   2476:  * configured.
                   2477:  *
                   2478:  * @param root The \ref axlNode used to configure the new document
                   2479:  * root. The reference received can be null. In this case, it is
                   2480:  * considered that the root node is being unset.
                   2481:  */
                   2482: void    axl_doc_set_root (axlDoc * doc, axlNode * root)
                   2483: {
                   2484:        axl_return_if_fail (doc);
                   2485: 
                   2486:        /* set the new root */
                   2487:        doc->rootNode = root;
                   2488: 
                   2489:        /* if the reference received is null, just return */
                   2490:        if (root == NULL)
                   2491:                return;
                   2492: 
                   2493:        /* set a refeference to the document root */
                   2494:        axl_node_set_doc (root, doc);
                   2495: 
                   2496:        return;
                   2497: }
                   2498: 
                   2499: /** 
                   2500:  * @internal
                   2501:  *
                   2502:  * @brief Allows to set the given axlNode to be child of the current
                   2503:  * parent.
                   2504:  *
                   2505:  * @param doc The \ref axlDoc reference where the \ref axlNode will be
                   2506:  * configured.
                   2507:  *
                   2508:  * @param node The \ref axlNode reference to set as a child for the
                   2509:  * parent node.
                   2510:  */
                   2511: void     axl_doc_set_child_current_parent (axlDoc * doc, axlNode * node)
                   2512: {
                   2513:        axlNode * parent;
                   2514: 
                   2515:        /* perform some environment checks */
                   2516:        axl_return_if_fail (doc);
                   2517:        axl_return_if_fail (node);
                   2518:        
                   2519:        parent = axl_stack_peek (doc->parentNode);
                   2520:        axl_return_if_fail (parent);
                   2521: 
                   2522:        /* set the child for the current parent */
                   2523:        axl_node_set_child (parent, node);
                   2524: 
                   2525:        /* set the new parent */
                   2526:        axl_stack_push (doc->parentNode, node);
                   2527: 
                   2528:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "pushed a new parent into the stack <%s>, current status after operation: %d",
                   2529:                   axl_node_get_name (node), axl_stack_size (doc->parentNode));
                   2530:        
                   2531:        return;
                   2532: }
                   2533: 
                   2534: /** 
                   2535:  * @internal Allows to make current \ref axlDoc to pop current parent
                   2536:  * node, making the new parent node the previously opened.
                   2537:  *
                   2538:  * This API is deprecated (internal function used in the past).
                   2539:  * 
                   2540:  * @param doc The \ref axlDoc where the pop operation will be
                   2541:  * performed.
                   2542:  */
                   2543: void     axl_doc_pop_current_parent       (axlDoc * doc)
                   2544: {
                   2545:        return;
                   2546: }
                   2547: 
                   2548: /** 
                   2549:  * @brief Allows to configure a PI target, with its content, on the given \ref axlDoc.
                   2550:  *
                   2551:  * A PI is a process instruction that is passed to the
                   2552:  * application. This process instruction has a target name, which
                   2553:  * acording to the standard is the application which should receive
                   2554:  * the target content and an optional target content associated.
                   2555:  *
                   2556:  * This function allows to configure (add) a new PI item inside the
                   2557:  * given xml document (\ref axlDoc). The PI content is optional. If
                   2558:  * provided NULL, the PI will only contain as information the PI
                   2559:  * target.
                   2560:  *
                   2561:  * Here is how a process instruction is used inside a xml document:
                   2562:  * \code
                   2563:  * <?xml version='1.0'>
                   2564:  * <?launch "some command" ?>
                   2565:  * <complex>
                   2566:  *    <?data "some data" ?>
                   2567:  *    <?data "more data" ?>
                   2568:  *    <data>
                   2569:  *       <row attr="20" />
                   2570:  *    </data>
                   2571:  * </complex>
                   2572:  * \endcode
                   2573:  *
                   2574:  * Previous example shows how to use PI (process instructions) from
                   2575:  * outside the xml root node (<b>complex</b>, and also how it is used
                   2576:  * from inside a xml node definition <b>complex</b>. 
                   2577:  *
                   2578:  * As you can see, PI elements could be used as many times as you want
                   2579:  * and places allowed to do so are just right before begining with the
                   2580:  * root node and inside xml node definitions.
                   2581:  * 
                   2582:  * @param doc The axlDocument where the PI will be added.
                   2583:  * @param target The PI target name.
                   2584:  * @param content The PI content (optional value).
                   2585:  */
                   2586: void      axl_doc_add_pi_target            (axlDoc * doc, 
                   2587:                                            char * target, 
                   2588:                                            char * content)
                   2589: {
                   2590:        axlPI * pi;
                   2591: 
                   2592:        /* perform some environmental checks */
                   2593:        axl_return_if_fail (doc);
                   2594:        axl_return_if_fail (target);
                   2595: 
                   2596:        /* create the PI element */
                   2597:        pi = axl_pi_create (target, content);
                   2598: 
                   2599:        /* add the PI */
                   2600:        axl_list_add (doc->piTargets, pi);
                   2601: 
                   2602:        return;
                   2603: }
                   2604: 
                   2605: /** 
                   2606:  * @brief Allows to check if the provided Processing instruction
                   2607:  * target is defined on the given xml document (\ref axlDoc).
                   2608:  *
                   2609:  * Processing instruction are a way to configure the xml document with
                   2610:  * processing information to instruct the application level that is
                   2611:  * going to consume the XML information.
                   2612:  *
                   2613:  * @param doc The document where the processing instruction will be read.
                   2614:  *
                   2615:  * @param pi_target The process instruction name.
                   2616:  * 
                   2617:  * @return axl_true is the processing instruction is defined,
                   2618:  * otherwise axl_false is returned.
                   2619:  */
                   2620: axl_bool      axl_doc_has_pi_target            (axlDoc * doc, char * pi_target)
                   2621: {
                   2622:        axlPI * pi;
                   2623:        int     iterator = 0;
                   2624:        int     length   = 0;
                   2625: 
                   2626:        
                   2627:        axl_return_val_if_fail (doc,       axl_false);
                   2628:        axl_return_val_if_fail (pi_target, axl_false);
                   2629: 
                   2630:        /* get the length for the items inserted */
                   2631:        length = axl_list_length (doc->piTargets);
                   2632:        while (iterator < length) {
                   2633:                /* for each item inserted */
                   2634:                pi = axl_list_get_nth (doc->piTargets, iterator);
                   2635:                /* only check the first ocurrency */
                   2636:                if (axl_cmp (pi->name, pi_target))
                   2637:                        return axl_true;
                   2638: 
                   2639:                iterator++;
                   2640:        }
                   2641:        
                   2642:        return axl_false;
                   2643: }
                   2644: 
                   2645: /** 
                   2646:  * @brief Allows to get current processing instruction content.
                   2647:  * 
                   2648:  * @param doc The document where the processing instruction is placed.
                   2649:  *
                   2650:  * @param pi_target The processing instruction target to get current
                   2651:  * content.
                   2652:  * 
                   2653:  * @return An internal reference to the process instruction target
                   2654:  * content. Value returned mustn't be deallocated
                   2655:  */
                   2656: char    * axl_doc_get_pi_target_content    (axlDoc * doc, char * pi_target)
                   2657: {
                   2658:        axlPI * pi;
                   2659:        int     iterator = 0;
                   2660:        int     length   = 0;
                   2661: 
                   2662:        axl_return_val_if_fail (doc,       NULL);
                   2663:        axl_return_val_if_fail (pi_target, NULL);
                   2664: 
                   2665:        /* get the length for the items inserted */
                   2666:        length = axl_list_length (doc->piTargets);
                   2667:        while (iterator < length) {
                   2668:                /* for each item inserted */
                   2669:                pi = axl_list_get_nth (doc->piTargets, iterator);
                   2670:                /* only check the first ocurrency */
                   2671:                if (axl_cmp (pi->name, pi_target))
                   2672:                        return pi->content;
                   2673: 
                   2674:                iterator++;
                   2675:        }
                   2676: 
                   2677:        return NULL;
                   2678: }
                   2679: 
                   2680: /** 
                   2681:  * @brief Allows to get a list which contains \ref axlPI nodes,
                   2682:  * representing all process instruction that the document has.
                   2683:  *
                   2684:  * While using PI, you can use the following functions to get PI
                   2685:  * information:
                   2686:  * 
                   2687:  *  - \ref axl_doc_has_pi_target
                   2688:  *  - \ref axl_doc_get_pi_target_content
                   2689:  *
                   2690:  * However, this function will return first ocurrency for PI found
                   2691:  * inside the xml document. If you don't use repeated PI elements, you
                   2692:  * won't find problems, but, if you need to iterate ever all PI found
                   2693:  * or you are using repeated PI, you can use this function as follows
                   2694:  * to get current pi elements:
                   2695:  * \code
                   2696:  * void show_all_pi (axlDoc * doc) 
                   2697:  * {
                   2698:  *      int       iterator;
                   2699:  *      axlPI   * pi;
                   2700:  *      axlList * PIs;
                   2701:  *
                   2702:  *      // get all PI target that the document has
                   2703:  *      PIs      = axl_doc_get_pi_target_list (doc);
                   2704:  *      iterator = 0;
                   2705:  *
                   2706:  *      while (iterator < axl_list_length (PIs)) {
                   2707:  *            // get next pi stored 
                   2708:  *            pi = axl_list_get_nth (PIs, iterator);
                   2709:  *
                   2710:  *            // do some stuff 
                   2711:  *            printf ("PI found target name=%s, content=%s\n",
                   2712:  *                    axl_pi_get_name (pi),
                   2713:  *                    axl_pi_get_content (pi));
                   2714:  *            
                   2715:  *            // update the iterator
                   2716:  *            iterator++;
                   2717:  *      }
                   2718:  *      return;
                   2719:  * }
                   2720:  * \endcode
                   2721:  * 
                   2722:  * @param doc The xml document (\ref axlDoc) where the process
                   2723:  * instruction will be returned.
                   2724:  * 
                   2725:  * @return A reference to the list of processing instruction that the
                   2726:  * xml document (\ref axlDoc) has.
                   2727:  */
                   2728: axlList * axl_doc_get_pi_target_list       (axlDoc * doc)
                   2729: {
                   2730:        axl_return_val_if_fail (doc,       NULL);
                   2731: 
                   2732:        return doc->piTargets;
                   2733: }
                   2734: 
                   2735: /** 
                   2736:  *
                   2737:  * @brief Allows to create a new \ref axlPI element. 
                   2738:  * 
                   2739:  * @param name The PI target name.
                   2740:  * @param content The PI content.
                   2741:  * 
                   2742:  * @return A newly allocated \ref axlPI element.
                   2743:  */
                   2744: axlPI * axl_pi_create (char * name, char * content)
                   2745: {
                   2746:        axlPI * pi;
                   2747: 
                   2748:        /* create the PI */
                   2749:        pi          = axl_new (axlPI, 1);
                   2750:        pi->name    = axl_strdup (name);
                   2751:        
                   2752:        /* copy the content if defined */
                   2753:        if (content != NULL)
                   2754:                pi->content = axl_strdup (content);
                   2755: 
                   2756:        return pi;
                   2757: }
                   2758: 
                   2759: /** 
                   2760:  * @brief Returns a newly allocated copy representing the same value
                   2761:  * as the provided \ref axlPI reference.
                   2762:  * 
                   2763:  * @param pi The pi reference received.
                   2764:  * 
                   2765:  * @return A reference to the \ref axlPI element or null if it fails.
                   2766:  */
                   2767: axlPI   * axl_pi_copy                      (axlPI  * pi)
                   2768: {
                   2769:        axlPI * _pi;
                   2770: 
                   2771:        axl_return_val_if_fail (pi, NULL);
                   2772: 
                   2773:        /* create the PI */
                   2774:        _pi          = axl_new (axlPI, 1);
                   2775:        _pi->name    = axl_strdup (pi->name);
                   2776:        
                   2777:        /* copy the content if defined */
                   2778:        if (pi->content != NULL)
                   2779:                _pi->content = axl_strdup (pi->content);
                   2780: 
                   2781:        return _pi;
                   2782: }
                   2783: 
                   2784: /** 
                   2785:  * @brief Allows to check if both provided process instructions are
                   2786:  * equal.
                   2787:  * 
                   2788:  * @param pi First process instruction to check.
                   2789:  * @param pi2 Second process instructions to check.
                   2790:  * 
                   2791:  * @return \ref axl_true if both process instructions are equal. If some
                   2792:  * of parameters received are NULL, the function will always return
                   2793:  * \ref axl_false.
                   2794:  */
                   2795: axl_bool      axl_pi_are_equal                 (axlPI * pi, 
                   2796:                                                axlPI * pi2)
                   2797: {
                   2798:        /* basic null reference check */
                   2799:        axl_return_val_if_fail (pi, axl_false);
                   2800:        axl_return_val_if_fail (pi2, axl_false);
                   2801: 
                   2802:        /* check internal data */
                   2803:        if (! axl_cmp (pi->name, pi2->name))
                   2804:                return axl_false;
                   2805: 
                   2806:        /* final check, both content must be equal */
                   2807:        return axl_cmp (pi->content, pi2->content);
                   2808: }
                   2809: 
                   2810: /** 
                   2811:  * @brief Allows to get current pi name from the given \ref axlPI
                   2812:  * reference.
                   2813:  *
                   2814:  * @param pi The PI reference where the name will returned.
                   2815:  * 
                   2816:  * @return A string representing the PI name. Returned value shouldn't
                   2817:  * be deallocated.
                   2818:  */
                   2819: char    * axl_pi_get_name                  (axlPI  * pi)
                   2820: {
                   2821:        axl_return_val_if_fail (pi, NULL);
                   2822: 
                   2823:        /* return current PI name */
                   2824:        return pi->name;
                   2825: }
                   2826: 
                   2827: /** 
                   2828:  * @brief Allows to get current optinal PI content.
                   2829:  * 
                   2830:  * @param pi The PI where the content will be returned.
                   2831:  * 
                   2832:  * @return A string representing the PI content. This value could be
                   2833:  * NULL because it is optional to be defined. Returned value must not
                   2834:  * be deallocated.
                   2835:  */
                   2836: char    * axl_pi_get_content               (axlPI  * pi)
                   2837: {
                   2838:        axl_return_val_if_fail (pi, NULL);
                   2839:        
                   2840:        /* return current PI content */
                   2841:        return pi->content;
                   2842: }
                   2843: 
                   2844: /** 
                   2845:  * @brief Deallocates memory used by the \ref axlPI target.
                   2846:  * 
                   2847:  * @param pi The target to destroy.
                   2848:  */
                   2849: void axl_pi_free (axlPI * pi)
                   2850: {
                   2851:        if (pi == NULL)
                   2852:                return;
                   2853: 
                   2854:        /* free PI target */
                   2855:        axl_free (pi->name);
                   2856:        axl_free (pi->content);
                   2857:        axl_free (pi);
                   2858:        return;
                   2859: }
                   2860: 
                   2861: /** 
                   2862:  * @internal Allows to get the number of bytes that the process
                   2863:  * instruction will take.
                   2864:  * 
                   2865:  * @param pi The process instruction.
                   2866:  * 
                   2867:  * @return A size or -1 if it fails.
                   2868:  */
                   2869: int       axl_pi_get_size                  (axlPI  * pi)
                   2870: {
                   2871:        axl_return_val_if_fail (pi, -1);
                   2872: 
                   2873:        /* <?name content?> */
                   2874:        return strlen (pi->name) + strlen (pi->content) + 5;
                   2875: }
                   2876: 
                   2877: /** 
                   2878:  * @internal
                   2879:  *
                   2880:  * Common implementation for \ref axl_doc_iterate and \ref axl_doc_iterate2.
                   2881:  */
                   2882: axl_bool __axl_doc_iterate_common (axlDoc            * doc, 
                   2883:                                   axlNode           * root,
                   2884:                                   AxlIterationMode    mode, 
                   2885:                                   axlIterationFunc    func, 
                   2886:                                   axlIterationFunc2   func2, 
                   2887:                                   axlPointer          ptr, 
                   2888:                                   axlPointer          ptr2)
                   2889: {
                   2890:        int        iterator;
                   2891:        axl_bool   was_removed = axl_false;
                   2892: 
                   2893:        axlNode  * node;
                   2894:        axlNode  * nodeAux;
                   2895: 
                   2896:        axlList  * pending;
                   2897: 
                   2898:        /* check first node */
                   2899:        axl_return_val_if_fail (root, axl_false);
                   2900: 
                   2901:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "notifying first node inside the iteration");
                   2902: 
                   2903:        /* notify first node found we pass in a null value because it
                   2904:           doesn't have a * parent. */
                   2905:        if (func && ! func (root, NULL, doc, &was_removed, ptr))
                   2906:                return axl_false;
                   2907:        if (func2 && ! func2 (root, NULL, doc, &was_removed, ptr, ptr2)) 
                   2908:                return axl_false;
                   2909: 
                   2910:        /* if the root node was removed, don't continue */
                   2911:        if (was_removed)
                   2912:                return axl_false;
                   2913: 
                   2914:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "continuing with next nodes");
                   2915:        
                   2916:        /* get childs */
                   2917:        pending  = axl_node_get_childs (root);
                   2918: 
                   2919:        /* for each pending node */
                   2920:        while (axl_list_length (pending) > 0) {
                   2921: 
                   2922:                /* get the first node inside the pending list */
                   2923:                node = axl_list_get_first (pending);
                   2924: 
                   2925:                /* remove the node node from the pending list and add
                   2926:                 * all childs */
                   2927:                axl_list_remove_first (pending);
                   2928: 
                   2929:                /* notify node found */
                   2930:                was_removed = axl_false;
                   2931:                if (func && ! func (node, axl_node_get_parent (node), doc, &was_removed, ptr)) {
                   2932:                        axl_list_free (pending);
                   2933:                        return axl_false;
                   2934:                }
                   2935: 
                   2936:                /* notify node found */
                   2937:                if (func2 && ! func2 (node, axl_node_get_parent (node), doc, &was_removed, ptr, ptr2)) {
                   2938:                        axl_list_free (pending);
                   2939:                        return axl_false;
                   2940:                }
                   2941: 
                   2942:                /* add all its childs */
                   2943:                if (!was_removed && axl_node_have_childs (node)) {
                   2944:                        
                   2945:                        /* get first child */
                   2946:                        nodeAux = axl_node_get_first_child (node);
                   2947: 
                   2948:                        /* get all items of the next level and add
                   2949:                         * them properly */
                   2950:                        iterator = 0;
                   2951:                        while (nodeAux != NULL) {
                   2952: 
                   2953:                                /* add to the pending list */
                   2954:                                switch (mode) {
                   2955:                                case DEEP_ITERATION:
                   2956:                                        /* add the element */
                   2957:                                        axl_list_add_at (pending, nodeAux, iterator);
                   2958:                                        
                   2959:                                        /* update the iterator */
                   2960:                                        iterator++;
                   2961:                                        break;
                   2962: 
                   2963:                                case WIDE_ITERATION:
                   2964:                                        /* add to the pending list */
                   2965:                                        axl_list_add (pending, nodeAux);
                   2966:                                        break;
                   2967:                                } /* end switch */
                   2968:        
                   2969: 
                   2970:                                /* update to the next */
                   2971:                                nodeAux = axl_node_get_next (nodeAux);
                   2972:                                
                   2973:                        } /* end while */
                   2974:                } /* end if */
                   2975: 
                   2976:                
                   2977:        } /* end while */
                   2978: 
                   2979:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "terminated iteration process, deallocating list: %d",
                   2980:                   axl_list_length (pending));
                   2981:        
                   2982:        axl_list_free (pending);
                   2983:        
                   2984:        /* iteration performed completely */
                   2985:        return axl_true;
                   2986: }
                   2987: 
                   2988: /** 
                   2989:  * @brief Allows to perform an iteration over the documented provided,
                   2990:  * visiting all nodes inside it.
                   2991:  *
                   2992:  * The function allows to configure the iteration module using \ref
                   2993:  * AxlIterationMode (mode variable) and providing a callback function
                   2994:  * that will be called for each node found (\ref axlIterationFunc).
                   2995:  *
                   2996:  * The function, optionall, allows to provide a user pointer that will
                   2997:  * be passed to the callback function. See documentation for the
                   2998:  * callback and the iteration module for more details.
                   2999:  *
                   3000:  * Here is an example:
                   3001:  * \code
                   3002:  * void perform_iteration (axlDoc * doc)
                   3003:  * {
                   3004:  *     // call to iterate
                   3005:  *     axl_doc_iterate (doc, 
                   3006:  *                      // visit childs before brothers
                   3007:  *                      DEEP_ITERATION, 
                   3008:  *                      // the func to execute: see below
                   3009:  *                      show_node_found, 
                   3010:  *                      // optional user pointer
                   3011:  *                      NULL);
                   3012:  * }
                   3013:  *
                   3014:  * axl_bool show_node_found (axlNode * node, axlNode * parent,
                   3015:  *                       axlDoc  * doc, axl_bool * was_removed, 
                   3016:  *                       axlPointer ptr)
                   3017:  * {
                   3018:  *      // Show node found 
                   3019:  *      printf ("Node found: %s\n", axl_node_get_name (node));
                   3020:  *
                   3021:  *      // If the node is removed inside the iteration
                   3022:  *      // using axl_node_remove or axl_node_replace, you
                   3023:  *      // must notify the iteration system using was_removed
                   3024:  *      // as follow: (* was_removed) = axl_true;
                   3025:  *      //
                   3026:  *      // If you don't remove anything, you don't need to do
                   3027:  *      // anything especial with was_removed.
                   3028:  *
                   3029:  *      // don't stop iteration
                   3030:  *      return axl_true;
                   3031:  * }
                   3032:  * \endcode
                   3033:  *
                   3034:  * See also alternative APIs:
                   3035:  * 
                   3036:  *   - \ref axl_doc_iterate_full
                   3037:  *   - \ref axl_doc_iterate_full_from
                   3038:  * 
                   3039:  * @param doc The xml document that will be iterated.
                   3040:  *
                   3041:  * @param mode The iterarion type to be performed.
                   3042:  *
                   3043:  * @param func The function to be called for each node found.
                   3044:  *
                   3045:  * @param ptr An user defined pointer that will be passed to the
                   3046:  * callback function.
                   3047:  *
                   3048:  * @return The function returns \ref axl_true if the iteration was
                   3049:  * performed over all nodes or \ref axl_false it it was stoped by the
                   3050:  * iteration function (by returning \ref axl_false to stop the
                   3051:  * iteration). The function also axl_false if the parameters provided doc
                   3052:  * or func are not defined.
                   3053:  */
                   3054: axl_bool      axl_doc_iterate                  (axlDoc           * doc,
                   3055:                                                AxlIterationMode   mode,
                   3056:                                                axlIterationFunc   func,
                   3057:                                                axlPointer         ptr)
                   3058: {
                   3059:        axlNode * root;
                   3060: 
                   3061:        /* check basic data */
                   3062:        axl_return_val_if_fail (doc, axl_false);
                   3063:        axl_return_val_if_fail (func, axl_false);
                   3064: 
                   3065:        /* get the root node where the iteration will start */
                   3066:        root = axl_doc_get_root (doc);
                   3067: 
                   3068:        /* call to common implementation */
                   3069:        return __axl_doc_iterate_common (doc, root, mode, func, NULL, ptr, NULL);
                   3070: 
                   3071: }
                   3072: 
                   3073: 
                   3074: /** 
                   3075:  * @brief Allows to perform an iteration over the documented provided,
                   3076:  * visiting all nodes inside it (with two user defined pointers support).
                   3077:  *
                   3078:  * The function allows to configure the iteration module using \ref
                   3079:  * AxlIterationMode (mode variable) and providing a callback function
                   3080:  * that will be called for each node found (\ref axlIterationFunc).
                   3081:  *
                   3082:  * The function, optionall, allows to provide two user pointer that will
                   3083:  * be passed to the callback function. See documentation for the
                   3084:  * callback and the iteration module for more details. See also \ref axl_doc_iterate.
                   3085:  *
                   3086:  * 
                   3087:  * @param doc The xml document that will be iterated.
                   3088:  *
                   3089:  * @param mode The iterarion type to be performed.
                   3090:  *
                   3091:  * @param func The function to be called for each node found.
                   3092:  *
                   3093:  * @param ptr An user defined pointer that will be passed to the
                   3094:  * callback function.
                   3095:  *
                   3096:  * @param ptr2 Second user defined pointer that will be passed to the
                   3097:  * callback function.
                   3098:  * 
                   3099:  *
                   3100:  * @return The function returns \ref axl_true if the iteration was
                   3101:  * performed over all nodes or \ref axl_false it it was stoped by the
                   3102:  * iteration function (by returning \ref axl_false to stop the
                   3103:  * iteration). The function also axl_false if the parameters provided doc
                   3104:  * or func are not defined.
                   3105:  */
                   3106: axl_bool      axl_doc_iterate_full             (axlDoc            * doc,
                   3107:                                                AxlIterationMode    mode,
                   3108:                                                axlIterationFunc2   func,
                   3109:                                                axlPointer          ptr,
                   3110:                                                axlPointer          ptr2)
                   3111: 
                   3112: {
                   3113:        axlNode * root;
                   3114: 
                   3115:        /* check basic data */
                   3116:        axl_return_val_if_fail (doc, axl_false);
                   3117:        axl_return_val_if_fail (func, axl_false);
                   3118: 
                   3119:        /* get the root node where the iteration will start */
                   3120:        root = axl_doc_get_root (doc);
                   3121:        
                   3122:        /* call to common implementation */
                   3123:        return __axl_doc_iterate_common (doc, root, mode, NULL, func, ptr, ptr2);
                   3124: }
                   3125: 
                   3126: /** 
                   3127:  * @brief Allows to perform a iteration operation but configuring
                   3128:  * where to start, discarding the rest content.
                   3129:  *
                   3130:  * See \ref axl_doc_iterate and \ref axl_doc_iterate_full for more
                   3131:  * details. This function works the same like previous but, unlike
                   3132:  * previous, this function doesn't use the default starting point: the
                   3133:  * root node (\ref axl_doc_get_root). The function allows to configure
                   3134:  * the node where to start the iteration operation. 
                   3135:  *
                   3136:  * This function is equivalent to \ref axl_doc_iterate_full calling if
                   3137:  * it use the root node document as value for <b>starting_from</b>.
                   3138:  * 
                   3139:  * @param doc The xml document that will be iterated.
                   3140:  *
                   3141:  * @param starting_from The \ref axlNode where the operation will
                   3142:  * start, discarding all content from ascending nodes, previous
                   3143:  * siblings and following sibligins. From a iteration perspective, the
                   3144:  * iteration opeeration.
                   3145:  *
                   3146:  * @param mode The iterarion type to be performed.
                   3147:  *
                   3148:  * @param func The function to be called for each node found.
                   3149:  *
                   3150:  * @param ptr An user defined pointer that will be passed to the
                   3151:  * callback function.
                   3152:  *
                   3153:  * @param ptr2 Second user defined pointer that will be passed to the
                   3154:  * callback function.
                   3155:  * 
                   3156:  *
                   3157:  * @return The function returns \ref axl_true if the iteration was
                   3158:  * performed over all nodes or \ref axl_false it it was stoped by the
                   3159:  * iteration function (by returning \ref axl_false to stop the
                   3160:  * iteration). The function also axl_false if the parameters provided doc
                   3161:  * or func are not defined.
                   3162:  */
                   3163: axl_bool      axl_doc_iterate_full_from        (axlDoc           * doc,
                   3164:                                                axlNode          * starting_from,
                   3165:                                                AxlIterationMode   mode,
                   3166:                                                axlIterationFunc2  func,
                   3167:                                                axlPointer         ptr,
                   3168:                                                axlPointer         ptr2)
                   3169: {
                   3170:        /* check basic data */
                   3171:        axl_return_val_if_fail (doc, axl_false);
                   3172:        axl_return_val_if_fail (func, axl_false);
                   3173: 
                   3174:        /* call to common implementation */
                   3175:        return __axl_doc_iterate_common (doc, starting_from, mode, NULL, func, ptr, ptr2);
                   3176: }
                   3177: 
                   3178: 
                   3179: /** 
                   3180:  * @brief Releases memory allocated by the \ref axlDoc object.
                   3181:  * 
                   3182:  * @param doc The \ref axlDoc object to unref.
                   3183:  */
                   3184: void     axl_doc_free         (axlDoc * doc)
                   3185: {
                   3186:        /* do not complain if an axlDoc reference is received */
                   3187:        if (doc == NULL)
                   3188:                return;
                   3189: 
                   3190:        /* free first root node */
                   3191:        if (doc->rootNode != NULL)
                   3192:                axl_node_free (doc->rootNode);
                   3193: 
                   3194:        /* free node hierarchy */
                   3195:        if (doc->parentNode != NULL)
                   3196:                axl_stack_free (doc->parentNode);
                   3197: 
                   3198:        /* free xml:space hierarchy */
                   3199:        if (doc->xmlPreserve != NULL)
                   3200:                axl_binary_stack_free (doc->xmlPreserve);
                   3201: 
                   3202:        /* free item factory */
                   3203:        if (doc->item_factory != NULL)
                   3204:                axl_factory_free (doc->item_factory);
                   3205: 
                   3206:        /* free content holding nodes factory */
                   3207:        if (doc->content_factory != NULL)
                   3208:                axl_factory_free (doc->content_factory);
                   3209: 
                   3210:        /* free attribute holding factory */
                   3211:        if (doc->attr_factory != NULL)
                   3212:                axl_factory_free (doc->attr_factory);
                   3213: 
                   3214:        /* free node factory */
                   3215:        if (doc->node_factory != NULL)
                   3216:                axl_factory_free (doc->node_factory);
                   3217: 
                   3218:        if (doc->str_factory != NULL)
                   3219:                axl_string_factory_free (doc->str_factory);
                   3220: 
                   3221:        /* free pi targets read */
                   3222:        if (doc->piTargets != NULL)
                   3223:                axl_list_free (doc->piTargets);
                   3224: 
                   3225:        /* free enconding allocated */
                   3226:        axl_free (doc->encoding);
                   3227:        axl_free (doc->encoding_found);
                   3228:        
                   3229:        /* free allocated version value */
                   3230:        axl_free (doc->version);
                   3231: 
                   3232:        /* free document allocated */
                   3233:        axl_free (doc);
                   3234: 
                   3235:        return;
                   3236: }
                   3237: 
                   3238: /** 
                   3239:  * @internal
                   3240:  *
                   3241:  * @brief Allows to consume comments found while reading xml files.
                   3242:  * 
                   3243:  * @param stream The axlStream where the comment is spected to be read.
                   3244:  *
                   3245:  * @param error An optional axlError where problem will be reported.
                   3246:  */
                   3247: axl_bool      axl_doc_consume_comments         (axlDoc * doc, axlStream * stream, axlError ** error)
                   3248: {
                   3249: 
                   3250:        axl_bool     found_item;
                   3251:        char       * content;
                   3252:        int          size;
                   3253: 
                   3254:        /* get current parent node */
                   3255:        axlNode * parent = (doc != NULL) ? axl_stack_peek (doc->parentNode) : NULL;
                   3256: 
                   3257:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking for comemnts");
                   3258: 
                   3259:        /* know, try to read comments a process instructions.  Do this
                   3260:         * until both fails. Do this until one of them find
                   3261:         * something. */
                   3262:        do {
                   3263:                /* flag the loop to end, and only end if both,
                   3264:                 * comments matching and PI matching fails. */
                   3265:                found_item = axl_false;
                   3266:                
                   3267:                /* get rid from spaces */
                   3268:                AXL_CONSUME_SPACES(stream);
                   3269: 
                   3270:                /* check for comments */
                   3271:                if (axl_stream_inspect (stream, "<!--", 4) > 0) {
                   3272: 
                   3273:                        /* get comment content */
                   3274:                        content = axl_stream_get_until_ref (stream, NULL, NULL, axl_true, &size, 1, "-->");
                   3275:                        if (content == NULL) {
                   3276:                                axl_error_new (-1, "detected an opened comment but not found the comment ending",
                   3277:                                               stream, error);
                   3278:                                axl_stream_free (stream);
                   3279:                                return axl_false;
                   3280:                        } 
                   3281: 
                   3282:                        /* store it */
                   3283:                        if (parent != NULL)
                   3284:                                axl_node_set_comment (parent, content, size);
                   3285:                        
                   3286:                        /* flag that we have found a comment */
                   3287:                        found_item = axl_true;
                   3288:                }
                   3289:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "now see for process instructions");
                   3290:        
                   3291:                /* get rid from spaces */
                   3292:                AXL_CONSUME_SPACES(stream);
                   3293: 
                   3294:                /* check for PI, only once the xml header have been processed */
                   3295:                if ((doc != NULL) && doc->headerProcess && (axl_stream_peek (stream, "<?", 2) > 0)) {
                   3296:                        
                   3297:                        if (! axl_doc_consume_pi (doc, axl_stack_peek (doc->parentNode), stream, error))
                   3298:                                return axl_false;
                   3299:                        found_item = axl_true;
                   3300:                }
                   3301:                
                   3302:                /* do not consume spaces if an item was found because
                   3303:                 * it is done again at the begin of the loop */
                   3304:                if (! found_item) {
                   3305:                        /* get rid from spaces */
                   3306:                        AXL_CONSUME_SPACES(stream);
                   3307:                }
                   3308:                
                   3309:                /* check to break-the-loop */
                   3310:        }while (found_item);
                   3311: 
                   3312:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "comments and pi parsed");
                   3313: 
                   3314:        /* axl_true value */
                   3315:        return axl_true;
                   3316: }
                   3317: 
                   3318: /** 
                   3319:  * @internal
                   3320:  *
                   3321:  * @brie Consumes Processing intructions that are directed to the
                   3322:  * application ans configuration or processing instructions.
                   3323:  * 
                   3324:  * @param doc The document there the information will be placed.
                   3325:  * 
                   3326:  * @param stream The stream where the data is being read.
                   3327:  *
                   3328:  * @param error An optional axlError where the information will be
                   3329:  * reported.
                   3330:  * 
                   3331:  * @return axl_true if not error was found, otherwise AXL_FASLSE is
                   3332:  * returned.
                   3333:  */
                   3334: axl_bool      axl_doc_consume_pi (axlDoc * doc, axlNode * node, 
                   3335:                                  axlStream * stream, axlError ** error)
                   3336: {
                   3337:        char  * string_aux;
                   3338:        char  * string_aux2;
                   3339:        int     matched_chunk;
                   3340:        
                   3341:        
                   3342:        /* check if a PI target was found */
                   3343: 
                   3344:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "calling to consume PI..");
                   3345: 
                   3346: 
                   3347:        if (axl_stream_peek (stream, "<?", 2) > 0) {
                   3348: 
                   3349:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a process instruction initialization");
                   3350: 
                   3351:                /* found a pi target initialization */
                   3352:                axl_stream_accept (stream);
                   3353:                
                   3354:                string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 3, 
                   3355:                                                   " ?>", "?>", " ");
                   3356:                /* check error reported */
                   3357:                if (string_aux == NULL) {
                   3358:                        axl_error_new (-1, "Found a error while reading the PI target name", stream, error);
                   3359:                        axl_stream_free (stream);
                   3360:                        return axl_false;
                   3361:                }
                   3362: 
                   3363:                /* check that the reserved xml word is not used for the PI target */
                   3364:                string_aux2 = axl_strdup (string_aux);
                   3365:                if (axl_cmp (axl_stream_to_lower (string_aux2), "xml")) {
                   3366:                        axl_free (string_aux2);
                   3367:                        axl_error_new (-1, "Using a reserved PI target name (xml), not allowed", stream, error);
                   3368:                        axl_stream_free (stream);
                   3369:                        return axl_false;
                   3370:                }
                   3371:                axl_free (string_aux2);
                   3372: 
                   3373: 
                   3374:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found PI target name: %s (terminator matched: %d)", 
                   3375:                           string_aux, matched_chunk);
                   3376: 
                   3377:                /* check which was the matched string */
                   3378:                if (matched_chunk == 0 || matched_chunk == 1) {
                   3379:                        /* seems that the PI target doesn't have more data associated, craete and return */
                   3380:                        if (node != NULL) {
                   3381:                                axl_node_add_pi_target (node, string_aux, NULL);
                   3382:                                return axl_true;
                   3383:                        }
                   3384:                        
                   3385:                        if (doc != NULL)
                   3386:                                axl_doc_add_pi_target (doc, string_aux, NULL);
                   3387:                        return axl_true;
                   3388:                }
                   3389: 
                   3390:                /* seems that we have additional content to be read */
                   3391:                if (matched_chunk == 2) {
                   3392:                        /* make a local copy for the PI target name
                   3393:                         * read previously */
                   3394:                        string_aux  = axl_strdup (string_aux);
                   3395:                        
                   3396:                        /* get the PI content */
                   3397:                        string_aux2 = axl_stream_get_until (stream, NULL, NULL, axl_true, 2, " ?>", "?>");
                   3398: 
                   3399:                        /* check error reported */
                   3400:                        if (string_aux2 == NULL) {
                   3401:                                axl_free (string_aux);
                   3402:                                axl_error_new (-1, "Found a error while reading the PI content", stream, error);
                   3403:                                axl_stream_free (stream);
                   3404:                                return axl_false;
                   3405:                        }
                   3406: 
                   3407:                        /* check the destination for the pi */                  
                   3408:                        if (node != NULL) {
                   3409:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished, adding PI (node) and its content");
                   3410: 
                   3411:                                axl_node_add_pi_target (node, string_aux, string_aux2);
                   3412:                                axl_free (string_aux);
                   3413:                                return axl_true;
                   3414:                        }
                   3415: 
                   3416: 
                   3417:                        if (doc != NULL) {
                   3418:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished, adding PI (doc) and its content");
                   3419:                                axl_doc_add_pi_target (doc, string_aux, string_aux2);
                   3420:                                axl_free (string_aux);
                   3421:                                return axl_true;
                   3422:                        }
                   3423: 
                   3424:                }
                   3425: 
                   3426:                /* check error reported */
                   3427:                axl_error_new (-1, "Found a error while reading the PI target name, unable to find PI terminator ?>", stream, error);
                   3428:                axl_stream_free (stream);
                   3429:                return axl_false;
                   3430:        }
                   3431: 
                   3432:        
                   3433:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "PI processing finished");
                   3434: 
                   3435: 
                   3436:        return axl_true;
                   3437: }
                   3438: 
                   3439: /** 
                   3440:  * @internal Function that allows to get axlFactory associated to
                   3441:  * the provided document.
                   3442:  * 
                   3443:  * @param doc The axl document that is requested to return its item
                   3444:  * factory.
                   3445:  * 
                   3446:  * @return An internal reference to the item factory. Do not dealloc.
                   3447:  */
                   3448: axlFactory * axl_doc_get_item_factory  (axlDoc * doc)
                   3449: {
                   3450:        return doc->item_factory;
                   3451: }
                   3452: 
                   3453: /** 
                   3454:  * @brief Allows to configure a handler that implements document
                   3455:  * detection and in such cases reconfigure \ref axlStream to act an a
                   3456:  * proper manner.
                   3457:  * 
                   3458:  * @param func The function to be configured.
                   3459:  *
                   3460:  * @param user_data User defined data to be provide to the function.
                   3461:  *
                   3462:  * @return A reference to the previously configured function.
                   3463:  */
                   3464: axlDocDetectCodification axl_doc_set_detect_codification_func (axlDocDetectCodification func, 
                   3465:                                                               axlPointer user_data)
                   3466: {
                   3467:        axlDocDetectCodification previous;
                   3468:        
                   3469:        /* configure handler and user defined pointer */
                   3470:        previous                 = detect_codification_func;
                   3471:        detect_codification_func = func;
                   3472:        detect_codification_data = user_data;
                   3473: 
                   3474:        return previous;
                   3475: }
                   3476: 
                   3477: /** 
                   3478:  * @brief Allows to configure the handler used to finally configure
                   3479:  * codification to be used for a particular \ref axlStream.
                   3480:  * 
                   3481:  * @param func The function to be called to configure codification.
                   3482:  *
                   3483:  * @param user_data A reference to user defined data to be passed to
                   3484:  * the function.
                   3485:  * 
                   3486:  * @return A refernece to the previous handler configured.
                   3487:  */
                   3488: axlDocConfigureCodification axl_doc_set_configure_codification_func (axlDocConfigureCodification func, 
                   3489:                                                                     axlPointer user_data)
                   3490: {
                   3491:        axlDocConfigureCodification previous;
                   3492:        
                   3493:        /* configure handler and user defined pointer */
                   3494:        previous                    = configure_codification_func;
                   3495:        configure_codification_func = func;
                   3496:        configure_codification_data = user_data;
                   3497: 
                   3498:        return previous;
                   3499: }
                   3500: 
                   3501: /* @} */

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