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

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

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