Bump to libxml2 2.9.7
[platform/upstream/libxml2.git] / xmlreader.c
1 /*
2  * xmlreader.c: implements the xmlTextReader streaming node API
3  *
4  * NOTE:
5  *   XmlTextReader.Normalization Property won't be supported, since
6  *     it makes the parser non compliant to the XML recommendation
7  *
8  * See Copyright for the status of this software.
9  *
10  * daniel@veillard.com
11  */
12
13 /*
14  * TODOs:
15  *   - XML Schemas validation
16  */
17 #define IN_LIBXML
18 #include "libxml.h"
19
20 #ifdef LIBXML_READER_ENABLED
21 #include <string.h> /* for memset() only ! */
22 #include <stdarg.h>
23
24 #ifdef HAVE_CTYPE_H
25 #include <ctype.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30
31 #include <libxml/xmlmemory.h>
32 #include <libxml/xmlIO.h>
33 #include <libxml/xmlreader.h>
34 #include <libxml/parserInternals.h>
35 #ifdef LIBXML_SCHEMAS_ENABLED
36 #include <libxml/relaxng.h>
37 #include <libxml/xmlschemas.h>
38 #endif
39 #include <libxml/uri.h>
40 #ifdef LIBXML_XINCLUDE_ENABLED
41 #include <libxml/xinclude.h>
42 #endif
43 #ifdef LIBXML_PATTERN_ENABLED
44 #include <libxml/pattern.h>
45 #endif
46
47 #include "buf.h"
48
49 #define MAX_ERR_MSG_SIZE 64000
50
51 /*
52  * The following VA_COPY was coded following an example in
53  * the Samba project.  It may not be sufficient for some
54  * esoteric implementations of va_list but (hopefully) will
55  * be sufficient for libxml2.
56  */
57 #ifndef VA_COPY
58   #ifdef HAVE_VA_COPY
59     #define VA_COPY(dest, src) va_copy(dest, src)
60   #else
61     #ifdef HAVE___VA_COPY
62       #define VA_COPY(dest,src) __va_copy(dest, src)
63     #else
64       #ifndef VA_LIST_IS_ARRAY
65         #define VA_COPY(dest,src) (dest) = (src)
66       #else
67         #include <string.h>
68         #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list))
69       #endif
70     #endif
71   #endif
72 #endif
73
74 /* #define DEBUG_CALLBACKS */
75 /* #define DEBUG_READER */
76
77 /**
78  * TODO:
79  *
80  * macro to flag unimplemented blocks
81  */
82 #define TODO                                                            \
83     xmlGenericError(xmlGenericErrorContext,                             \
84             "Unimplemented block at %s:%d\n",                           \
85             __FILE__, __LINE__);
86
87 #ifdef DEBUG_READER
88 #define DUMP_READER xmlTextReaderDebug(reader);
89 #else
90 #define DUMP_READER
91 #endif
92
93 #define CHUNK_SIZE 512
94 /************************************************************************
95  *                                                                      *
96  *      The parser: maps the Text Reader API on top of the existing     *
97  *              parsing routines building a tree                        *
98  *                                                                      *
99  ************************************************************************/
100
101 #define XML_TEXTREADER_INPUT    1
102 #define XML_TEXTREADER_CTXT     2
103
104 typedef enum {
105     XML_TEXTREADER_NONE = -1,
106     XML_TEXTREADER_START= 0,
107     XML_TEXTREADER_ELEMENT= 1,
108     XML_TEXTREADER_END= 2,
109     XML_TEXTREADER_EMPTY= 3,
110     XML_TEXTREADER_BACKTRACK= 4,
111     XML_TEXTREADER_DONE= 5,
112     XML_TEXTREADER_ERROR= 6
113 } xmlTextReaderState;
114
115 typedef enum {
116     XML_TEXTREADER_NOT_VALIDATE = 0,
117     XML_TEXTREADER_VALIDATE_DTD = 1,
118     XML_TEXTREADER_VALIDATE_RNG = 2,
119     XML_TEXTREADER_VALIDATE_XSD = 4
120 } xmlTextReaderValidate;
121
122 struct _xmlTextReader {
123     int                         mode;   /* the parsing mode */
124     xmlDocPtr                   doc;    /* when walking an existing doc */
125     xmlTextReaderValidate       validate;/* is there any validation */
126     int                         allocs; /* what structure were deallocated */
127     xmlTextReaderState          state;
128     xmlParserCtxtPtr            ctxt;   /* the parser context */
129     xmlSAXHandlerPtr            sax;    /* the parser SAX callbacks */
130     xmlParserInputBufferPtr     input;  /* the input */
131     startElementSAXFunc         startElement;/* initial SAX callbacks */
132     endElementSAXFunc           endElement;  /* idem */
133     startElementNsSAX2Func      startElementNs;/* idem */
134     endElementNsSAX2Func        endElementNs;  /* idem */
135     charactersSAXFunc           characters;
136     cdataBlockSAXFunc           cdataBlock;
137     unsigned int                base;   /* base of the segment in the input */
138     unsigned int                cur;    /* current position in the input */
139     xmlNodePtr                  node;   /* current node */
140     xmlNodePtr                  curnode;/* current attribute node */
141     int                         depth;  /* depth of the current node */
142     xmlNodePtr                  faketext;/* fake xmlNs chld */
143     int                         preserve;/* preserve the resulting document */
144     xmlBufPtr                   buffer; /* used to return const xmlChar * */
145     xmlDictPtr                  dict;   /* the context dictionary */
146
147     /* entity stack when traversing entities content */
148     xmlNodePtr         ent;          /* Current Entity Ref Node */
149     int                entNr;        /* Depth of the entities stack */
150     int                entMax;       /* Max depth of the entities stack */
151     xmlNodePtr        *entTab;       /* array of entities */
152
153     /* error handling */
154     xmlTextReaderErrorFunc errorFunc;    /* callback function */
155     void                  *errorFuncArg; /* callback function user argument */
156
157 #ifdef LIBXML_SCHEMAS_ENABLED
158     /* Handling of RelaxNG validation */
159     xmlRelaxNGPtr          rngSchemas;  /* The Relax NG schemas */
160     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
161     int                    rngPreserveCtxt; /* 1 if the context was provided by the user */
162     int                    rngValidErrors;/* The number of errors detected */
163     xmlNodePtr             rngFullNode; /* the node if RNG not progressive */
164     /* Handling of Schemas validation */
165     xmlSchemaPtr          xsdSchemas;   /* The Schemas schemas */
166     xmlSchemaValidCtxtPtr xsdValidCtxt;/* The Schemas validation context */
167     int                   xsdPreserveCtxt; /* 1 if the context was provided by the user */
168     int                   xsdValidErrors;/* The number of errors detected */
169     xmlSchemaSAXPlugPtr   xsdPlug;      /* the schemas plug in SAX pipeline */
170 #endif
171 #ifdef LIBXML_XINCLUDE_ENABLED
172     /* Handling of XInclude processing */
173     int                xinclude;        /* is xinclude asked for */
174     const xmlChar *    xinclude_name;   /* the xinclude name from dict */
175     xmlXIncludeCtxtPtr xincctxt;        /* the xinclude context */
176     int                in_xinclude;     /* counts for xinclude */
177 #endif
178 #ifdef LIBXML_PATTERN_ENABLED
179     int                patternNr;       /* number of preserve patterns */
180     int                patternMax;      /* max preserve patterns */
181     xmlPatternPtr     *patternTab;      /* array of preserve patterns */
182 #endif
183     int                preserves;       /* level of preserves */
184     int                parserFlags;     /* the set of options set */
185     /* Structured error handling */
186     xmlStructuredErrorFunc sErrorFunc;  /* callback function */
187 };
188
189 #define NODE_IS_EMPTY           0x1
190 #define NODE_IS_PRESERVED       0x2
191 #define NODE_IS_SPRESERVED      0x4
192
193 /**
194  * CONSTSTR:
195  *
196  * Macro used to return an interned string
197  */
198 #define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1)
199 #define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str))
200
201 static int xmlTextReaderReadTree(xmlTextReaderPtr reader);
202 static int xmlTextReaderNextTree(xmlTextReaderPtr reader);
203
204 /************************************************************************
205  *                                                                      *
206  *      Our own version of the freeing routines as we recycle nodes     *
207  *                                                                      *
208  ************************************************************************/
209 /**
210  * DICT_FREE:
211  * @str:  a string
212  *
213  * Free a string if it is not owned by the "dict" dictionary in the
214  * current scope
215  */
216 #define DICT_FREE(str)                                          \
217         if ((str) && ((!dict) ||                                \
218             (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
219             xmlFree((char *)(str));
220
221 static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur);
222 static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur);
223
224 /**
225  * xmlFreeID:
226  * @not:  A id
227  *
228  * Deallocate the memory used by an id definition
229  */
230 static void
231 xmlFreeID(xmlIDPtr id) {
232     xmlDictPtr dict = NULL;
233
234     if (id == NULL) return;
235
236     if (id->doc != NULL)
237         dict = id->doc->dict;
238
239     if (id->value != NULL)
240         DICT_FREE(id->value)
241     xmlFree(id);
242 }
243
244 /**
245  * xmlTextReaderRemoveID:
246  * @doc:  the document
247  * @attr:  the attribute
248  *
249  * Remove the given attribute from the ID table maintained internally.
250  *
251  * Returns -1 if the lookup failed and 0 otherwise
252  */
253 static int
254 xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
255     xmlIDTablePtr table;
256     xmlIDPtr id;
257     xmlChar *ID;
258
259     if (doc == NULL) return(-1);
260     if (attr == NULL) return(-1);
261     table = (xmlIDTablePtr) doc->ids;
262     if (table == NULL)
263         return(-1);
264
265     ID = xmlNodeListGetString(doc, attr->children, 1);
266     if (ID == NULL)
267         return(-1);
268     id = xmlHashLookup(table, ID);
269     xmlFree(ID);
270     if (id == NULL || id->attr != attr) {
271         return(-1);
272     }
273     id->name = attr->name;
274     id->attr = NULL;
275     return(0);
276 }
277
278 /**
279  * xmlTextReaderFreeProp:
280  * @reader:  the xmlTextReaderPtr used
281  * @cur:  the node
282  *
283  * Free a node.
284  */
285 static void
286 xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
287     xmlDictPtr dict;
288
289     if ((reader != NULL) && (reader->ctxt != NULL))
290         dict = reader->ctxt->dict;
291     else
292         dict = NULL;
293     if (cur == NULL) return;
294
295     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
296         xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
297
298     /* Check for ID removal -> leading to invalid references ! */
299     if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
300         ((cur->parent->doc->intSubset != NULL) ||
301          (cur->parent->doc->extSubset != NULL))) {
302         if (xmlIsID(cur->parent->doc, cur->parent, cur))
303             xmlTextReaderRemoveID(cur->parent->doc, cur);
304     }
305     if (cur->children != NULL)
306         xmlTextReaderFreeNodeList(reader, cur->children);
307
308     DICT_FREE(cur->name);
309     if ((reader != NULL) && (reader->ctxt != NULL) &&
310         (reader->ctxt->freeAttrsNr < 100)) {
311         cur->next = reader->ctxt->freeAttrs;
312         reader->ctxt->freeAttrs = cur;
313         reader->ctxt->freeAttrsNr++;
314     } else {
315         xmlFree(cur);
316     }
317 }
318
319 /**
320  * xmlTextReaderFreePropList:
321  * @reader:  the xmlTextReaderPtr used
322  * @cur:  the first property in the list
323  *
324  * Free a property and all its siblings, all the children are freed too.
325  */
326 static void
327 xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
328     xmlAttrPtr next;
329
330     while (cur != NULL) {
331         next = cur->next;
332         xmlTextReaderFreeProp(reader, cur);
333         cur = next;
334     }
335 }
336
337 /**
338  * xmlTextReaderFreeNodeList:
339  * @reader:  the xmlTextReaderPtr used
340  * @cur:  the first node in the list
341  *
342  * Free a node and all its siblings, this is a recursive behaviour, all
343  * the children are freed too.
344  */
345 static void
346 xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
347     xmlNodePtr next;
348     xmlDictPtr dict;
349
350     if ((reader != NULL) && (reader->ctxt != NULL))
351         dict = reader->ctxt->dict;
352     else
353         dict = NULL;
354     if (cur == NULL) return;
355     if (cur->type == XML_NAMESPACE_DECL) {
356         xmlFreeNsList((xmlNsPtr) cur);
357         return;
358     }
359     if ((cur->type == XML_DOCUMENT_NODE) ||
360         (cur->type == XML_HTML_DOCUMENT_NODE)) {
361         xmlFreeDoc((xmlDocPtr) cur);
362         return;
363     }
364     while (cur != NULL) {
365         next = cur->next;
366         /* unroll to speed up freeing the document */
367         if (cur->type != XML_DTD_NODE) {
368
369             if ((cur->children != NULL) &&
370                 (cur->type != XML_ENTITY_REF_NODE)) {
371                 if (cur->children->parent == cur)
372                     xmlTextReaderFreeNodeList(reader, cur->children);
373                 cur->children = NULL;
374             }
375
376             if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
377                 xmlDeregisterNodeDefaultValue(cur);
378
379             if (((cur->type == XML_ELEMENT_NODE) ||
380                  (cur->type == XML_XINCLUDE_START) ||
381                  (cur->type == XML_XINCLUDE_END)) &&
382                 (cur->properties != NULL))
383                 xmlTextReaderFreePropList(reader, cur->properties);
384             if ((cur->content != (xmlChar *) &(cur->properties)) &&
385                 (cur->type != XML_ELEMENT_NODE) &&
386                 (cur->type != XML_XINCLUDE_START) &&
387                 (cur->type != XML_XINCLUDE_END) &&
388                 (cur->type != XML_ENTITY_REF_NODE)) {
389                 DICT_FREE(cur->content);
390             }
391             if (((cur->type == XML_ELEMENT_NODE) ||
392                  (cur->type == XML_XINCLUDE_START) ||
393                  (cur->type == XML_XINCLUDE_END)) &&
394                 (cur->nsDef != NULL))
395                 xmlFreeNsList(cur->nsDef);
396
397             /*
398              * we don't free element names here they are interned now
399              */
400             if ((cur->type != XML_TEXT_NODE) &&
401                 (cur->type != XML_COMMENT_NODE))
402                 DICT_FREE(cur->name);
403             if (((cur->type == XML_ELEMENT_NODE) ||
404                  (cur->type == XML_TEXT_NODE)) &&
405                 (reader != NULL) && (reader->ctxt != NULL) &&
406                 (reader->ctxt->freeElemsNr < 100)) {
407                 cur->next = reader->ctxt->freeElems;
408                 reader->ctxt->freeElems = cur;
409                 reader->ctxt->freeElemsNr++;
410             } else {
411                 xmlFree(cur);
412             }
413         }
414         cur = next;
415     }
416 }
417
418 /**
419  * xmlTextReaderFreeNode:
420  * @reader:  the xmlTextReaderPtr used
421  * @cur:  the node
422  *
423  * Free a node, this is a recursive behaviour, all the children are freed too.
424  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
425  */
426 static void
427 xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
428     xmlDictPtr dict;
429
430     if ((reader != NULL) && (reader->ctxt != NULL))
431         dict = reader->ctxt->dict;
432     else
433         dict = NULL;
434     if (cur->type == XML_DTD_NODE) {
435         xmlFreeDtd((xmlDtdPtr) cur);
436         return;
437     }
438     if (cur->type == XML_NAMESPACE_DECL) {
439         xmlFreeNs((xmlNsPtr) cur);
440         return;
441     }
442     if (cur->type == XML_ATTRIBUTE_NODE) {
443         xmlTextReaderFreeProp(reader, (xmlAttrPtr) cur);
444         return;
445     }
446
447     if ((cur->children != NULL) &&
448         (cur->type != XML_ENTITY_REF_NODE)) {
449         if (cur->children->parent == cur)
450             xmlTextReaderFreeNodeList(reader, cur->children);
451         cur->children = NULL;
452     }
453
454     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
455         xmlDeregisterNodeDefaultValue(cur);
456
457     if (((cur->type == XML_ELEMENT_NODE) ||
458          (cur->type == XML_XINCLUDE_START) ||
459          (cur->type == XML_XINCLUDE_END)) &&
460         (cur->properties != NULL))
461         xmlTextReaderFreePropList(reader, cur->properties);
462     if ((cur->content != (xmlChar *) &(cur->properties)) &&
463         (cur->type != XML_ELEMENT_NODE) &&
464         (cur->type != XML_XINCLUDE_START) &&
465         (cur->type != XML_XINCLUDE_END) &&
466         (cur->type != XML_ENTITY_REF_NODE)) {
467         DICT_FREE(cur->content);
468     }
469     if (((cur->type == XML_ELEMENT_NODE) ||
470          (cur->type == XML_XINCLUDE_START) ||
471          (cur->type == XML_XINCLUDE_END)) &&
472         (cur->nsDef != NULL))
473         xmlFreeNsList(cur->nsDef);
474
475     /*
476      * we don't free names here they are interned now
477      */
478     if ((cur->type != XML_TEXT_NODE) &&
479         (cur->type != XML_COMMENT_NODE))
480         DICT_FREE(cur->name);
481
482     if (((cur->type == XML_ELEMENT_NODE) ||
483          (cur->type == XML_TEXT_NODE)) &&
484         (reader != NULL) && (reader->ctxt != NULL) &&
485         (reader->ctxt->freeElemsNr < 100)) {
486         cur->next = reader->ctxt->freeElems;
487         reader->ctxt->freeElems = cur;
488         reader->ctxt->freeElemsNr++;
489     } else {
490         xmlFree(cur);
491     }
492 }
493
494 /**
495  * xmlTextReaderFreeIDTable:
496  * @table:  An id table
497  *
498  * Deallocate the memory used by an ID hash table.
499  */
500 static void
501 xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
502     xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
503 }
504
505 /**
506  * xmlTextReaderFreeDoc:
507  * @reader:  the xmlTextReaderPtr used
508  * @cur:  pointer to the document
509  *
510  * Free up all the structures used by a document, tree included.
511  */
512 static void
513 xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
514     xmlDtdPtr extSubset, intSubset;
515
516     if (cur == NULL) return;
517
518     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
519         xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
520
521     /*
522      * Do this before freeing the children list to avoid ID lookups
523      */
524     if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
525     cur->ids = NULL;
526     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
527     cur->refs = NULL;
528     extSubset = cur->extSubset;
529     intSubset = cur->intSubset;
530     if (intSubset == extSubset)
531         extSubset = NULL;
532     if (extSubset != NULL) {
533         xmlUnlinkNode((xmlNodePtr) cur->extSubset);
534         cur->extSubset = NULL;
535         xmlFreeDtd(extSubset);
536     }
537     if (intSubset != NULL) {
538         xmlUnlinkNode((xmlNodePtr) cur->intSubset);
539         cur->intSubset = NULL;
540         xmlFreeDtd(intSubset);
541     }
542
543     if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);
544
545     if (cur->version != NULL) xmlFree((char *) cur->version);
546     if (cur->name != NULL) xmlFree((char *) cur->name);
547     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
548     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
549     if (cur->URL != NULL) xmlFree((char *) cur->URL);
550     if (cur->dict != NULL) xmlDictFree(cur->dict);
551
552     xmlFree(cur);
553 }
554
555 /************************************************************************
556  *                                                                      *
557  *                      The reader core parser                          *
558  *                                                                      *
559  ************************************************************************/
560 #ifdef DEBUG_READER
561 static void
562 xmlTextReaderDebug(xmlTextReaderPtr reader) {
563     if ((reader == NULL) || (reader->ctxt == NULL)) {
564         fprintf(stderr, "xmlTextReader NULL\n");
565         return;
566     }
567     fprintf(stderr, "xmlTextReader: state %d depth %d ",
568             reader->state, reader->depth);
569     if (reader->node == NULL) {
570         fprintf(stderr, "node = NULL\n");
571     } else {
572         fprintf(stderr, "node %s\n", reader->node->name);
573     }
574     fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
575             reader->base, reader->cur, reader->ctxt->nodeNr);
576     if (reader->input->buffer == NULL) {
577         fprintf(stderr, "buffer is NULL\n");
578     } else {
579 #ifdef LIBXML_DEBUG_ENABLED
580         xmlDebugDumpString(stderr,
581                 &reader->input->buffer->content[reader->cur]);
582 #endif
583         fprintf(stderr, "\n");
584     }
585 }
586 #endif
587
588 /**
589  * xmlTextReaderEntPush:
590  * @reader:  the xmlTextReaderPtr used
591  * @value:  the entity reference node
592  *
593  * Pushes a new entity reference node on top of the entities stack
594  *
595  * Returns 0 in case of error, the index in the stack otherwise
596  */
597 static int
598 xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
599 {
600     if (reader->entMax <= 0) {
601         reader->entMax = 10;
602         reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
603                                                   sizeof(reader->entTab[0]));
604         if (reader->entTab == NULL) {
605             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
606             return (0);
607         }
608     }
609     if (reader->entNr >= reader->entMax) {
610         reader->entMax *= 2;
611         reader->entTab =
612             (xmlNodePtr *) xmlRealloc(reader->entTab,
613                                       reader->entMax *
614                                       sizeof(reader->entTab[0]));
615         if (reader->entTab == NULL) {
616             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
617             return (0);
618         }
619     }
620     reader->entTab[reader->entNr] = value;
621     reader->ent = value;
622     return (reader->entNr++);
623 }
624
625 /**
626  * xmlTextReaderEntPop:
627  * @reader:  the xmlTextReaderPtr used
628  *
629  * Pops the top element entity from the entities stack
630  *
631  * Returns the entity just removed
632  */
633 static xmlNodePtr
634 xmlTextReaderEntPop(xmlTextReaderPtr reader)
635 {
636     xmlNodePtr ret;
637
638     if (reader->entNr <= 0)
639         return (NULL);
640     reader->entNr--;
641     if (reader->entNr > 0)
642         reader->ent = reader->entTab[reader->entNr - 1];
643     else
644         reader->ent = NULL;
645     ret = reader->entTab[reader->entNr];
646     reader->entTab[reader->entNr] = NULL;
647     return (ret);
648 }
649
650 /**
651  * xmlTextReaderStartElement:
652  * @ctx: the user data (XML parser context)
653  * @fullname:  The element name, including namespace prefix
654  * @atts:  An array of name/value attributes pairs, NULL terminated
655  *
656  * called when an opening tag has been processed.
657  */
658 static void
659 xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
660                           const xmlChar **atts) {
661     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
662     xmlTextReaderPtr reader = ctxt->_private;
663
664 #ifdef DEBUG_CALLBACKS
665     printf("xmlTextReaderStartElement(%s)\n", fullname);
666 #endif
667     if ((reader != NULL) && (reader->startElement != NULL)) {
668         reader->startElement(ctx, fullname, atts);
669         if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
670             (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
671             (ctxt->input->cur[1] == '>'))
672             ctxt->node->extra = NODE_IS_EMPTY;
673     }
674     if (reader != NULL)
675         reader->state = XML_TEXTREADER_ELEMENT;
676 }
677
678 /**
679  * xmlTextReaderEndElement:
680  * @ctx: the user data (XML parser context)
681  * @fullname:  The element name, including namespace prefix
682  *
683  * called when an ending tag has been processed.
684  */
685 static void
686 xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
687     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
688     xmlTextReaderPtr reader = ctxt->_private;
689
690 #ifdef DEBUG_CALLBACKS
691     printf("xmlTextReaderEndElement(%s)\n", fullname);
692 #endif
693     if ((reader != NULL) && (reader->endElement != NULL)) {
694         reader->endElement(ctx, fullname);
695     }
696 }
697
698 /**
699  * xmlTextReaderStartElementNs:
700  * @ctx: the user data (XML parser context)
701  * @localname:  the local name of the element
702  * @prefix:  the element namespace prefix if available
703  * @URI:  the element namespace name if available
704  * @nb_namespaces:  number of namespace definitions on that node
705  * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
706  * @nb_attributes:  the number of attributes on that node
707  * nb_defaulted:  the number of defaulted attributes.
708  * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
709  *               attribute values.
710  *
711  * called when an opening tag has been processed.
712  */
713 static void
714 xmlTextReaderStartElementNs(void *ctx,
715                       const xmlChar *localname,
716                       const xmlChar *prefix,
717                       const xmlChar *URI,
718                       int nb_namespaces,
719                       const xmlChar **namespaces,
720                       int nb_attributes,
721                       int nb_defaulted,
722                       const xmlChar **attributes)
723 {
724     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
725     xmlTextReaderPtr reader = ctxt->_private;
726
727 #ifdef DEBUG_CALLBACKS
728     printf("xmlTextReaderStartElementNs(%s)\n", localname);
729 #endif
730     if ((reader != NULL) && (reader->startElementNs != NULL)) {
731         reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
732                                namespaces, nb_attributes, nb_defaulted,
733                                attributes);
734         if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
735             (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
736             (ctxt->input->cur[1] == '>'))
737             ctxt->node->extra = NODE_IS_EMPTY;
738     }
739     if (reader != NULL)
740         reader->state = XML_TEXTREADER_ELEMENT;
741 }
742
743 /**
744  * xmlTextReaderEndElementNs:
745  * @ctx: the user data (XML parser context)
746  * @localname:  the local name of the element
747  * @prefix:  the element namespace prefix if available
748  * @URI:  the element namespace name if available
749  *
750  * called when an ending tag has been processed.
751  */
752 static void
753 xmlTextReaderEndElementNs(void *ctx,
754                           const xmlChar * localname,
755                           const xmlChar * prefix,
756                           const xmlChar * URI)
757 {
758     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
759     xmlTextReaderPtr reader = ctxt->_private;
760
761 #ifdef DEBUG_CALLBACKS
762     printf("xmlTextReaderEndElementNs(%s)\n", localname);
763 #endif
764     if ((reader != NULL) && (reader->endElementNs != NULL)) {
765         reader->endElementNs(ctx, localname, prefix, URI);
766     }
767 }
768
769
770 /**
771  * xmlTextReaderCharacters:
772  * @ctx: the user data (XML parser context)
773  * @ch:  a xmlChar string
774  * @len: the number of xmlChar
775  *
776  * receiving some chars from the parser.
777  */
778 static void
779 xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
780 {
781     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
782     xmlTextReaderPtr reader = ctxt->_private;
783
784 #ifdef DEBUG_CALLBACKS
785     printf("xmlTextReaderCharacters()\n");
786 #endif
787     if ((reader != NULL) && (reader->characters != NULL)) {
788         reader->characters(ctx, ch, len);
789     }
790 }
791
792 /**
793  * xmlTextReaderCDataBlock:
794  * @ctx: the user data (XML parser context)
795  * @value:  The pcdata content
796  * @len:  the block length
797  *
798  * called when a pcdata block has been parsed
799  */
800 static void
801 xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
802 {
803     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
804     xmlTextReaderPtr reader = ctxt->_private;
805
806 #ifdef DEBUG_CALLBACKS
807     printf("xmlTextReaderCDataBlock()\n");
808 #endif
809     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
810         reader->cdataBlock(ctx, ch, len);
811     }
812 }
813
814 /**
815  * xmlTextReaderPushData:
816  * @reader:  the xmlTextReaderPtr used
817  *
818  * Push data down the progressive parser until a significant callback
819  * got raised.
820  *
821  * Returns -1 in case of failure, 0 otherwise
822  */
823 static int
824 xmlTextReaderPushData(xmlTextReaderPtr reader) {
825     xmlBufPtr inbuf;
826     int val, s;
827     xmlTextReaderState oldstate;
828     int alloc;
829
830     if ((reader->input == NULL) || (reader->input->buffer == NULL))
831         return(-1);
832
833     oldstate = reader->state;
834     reader->state = XML_TEXTREADER_NONE;
835     inbuf = reader->input->buffer;
836     alloc = xmlBufGetAllocationScheme(inbuf);
837
838     while (reader->state == XML_TEXTREADER_NONE) {
839         if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
840             /*
841              * Refill the buffer unless we are at the end of the stream
842              */
843             if (reader->mode != XML_TEXTREADER_MODE_EOF) {
844                 val = xmlParserInputBufferRead(reader->input, 4096);
845                 if ((val == 0) &&
846                     (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
847                     if (xmlBufUse(inbuf) == reader->cur) {
848                         reader->mode = XML_TEXTREADER_MODE_EOF;
849                         reader->state = oldstate;
850                     }
851                 } else if (val < 0) {
852                     reader->mode = XML_TEXTREADER_MODE_EOF;
853                     reader->state = oldstate;
854                     if ((oldstate != XML_TEXTREADER_START) ||
855                         (reader->ctxt->myDoc != NULL))
856                         return(val);
857                 } else if (val == 0) {
858                     /* mark the end of the stream and process the remains */
859                     reader->mode = XML_TEXTREADER_MODE_EOF;
860                     break;
861                 }
862
863             } else
864                 break;
865         }
866         /*
867          * parse by block of CHUNK_SIZE bytes, various tests show that
868          * it's the best tradeoff at least on a 1.2GH Duron
869          */
870         if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
871             val = xmlParseChunk(reader->ctxt,
872                  (const char *) xmlBufContent(inbuf) + reader->cur,
873                                 CHUNK_SIZE, 0);
874             reader->cur += CHUNK_SIZE;
875             if (val != 0)
876                 reader->ctxt->wellFormed = 0;
877             if (reader->ctxt->wellFormed == 0)
878                 break;
879         } else {
880             s = xmlBufUse(inbuf) - reader->cur;
881             val = xmlParseChunk(reader->ctxt,
882                  (const char *) xmlBufContent(inbuf) + reader->cur,
883                                 s, 0);
884             reader->cur += s;
885             if (val != 0)
886                 reader->ctxt->wellFormed = 0;
887             break;
888         }
889     }
890
891     /*
892      * Discard the consumed input when needed and possible
893      */
894     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
895         if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
896             if ((reader->cur >= 4096) &&
897                 (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
898                 val = xmlBufShrink(inbuf, reader->cur);
899                 if (val >= 0) {
900                     reader->cur -= val;
901                 }
902             }
903         }
904     }
905
906     /*
907      * At the end of the stream signal that the work is done to the Push
908      * parser.
909      */
910     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
911         if (reader->state != XML_TEXTREADER_DONE) {
912             s = xmlBufUse(inbuf) - reader->cur;
913             val = xmlParseChunk(reader->ctxt,
914                  (const char *) xmlBufContent(inbuf) + reader->cur,
915                                 s, 1);
916             reader->cur = xmlBufUse(inbuf);
917             reader->state  = XML_TEXTREADER_DONE;
918             if (val != 0) {
919                 if (reader->ctxt->wellFormed)
920                     reader->ctxt->wellFormed = 0;
921                 else
922                     return(-1);
923             }
924         }
925     }
926     reader->state = oldstate;
927     if (reader->ctxt->wellFormed == 0) {
928         reader->mode = XML_TEXTREADER_MODE_EOF;
929         return(-1);
930     }
931
932     return(0);
933 }
934
935 #ifdef LIBXML_REGEXP_ENABLED
936 /**
937  * xmlTextReaderValidatePush:
938  * @reader:  the xmlTextReaderPtr used
939  *
940  * Push the current node for validation
941  */
942 static void
943 xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) {
944     xmlNodePtr node = reader->node;
945
946 #ifdef LIBXML_VALID_ENABLED
947     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
948         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
949         if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
950             reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
951                                     reader->ctxt->myDoc, node, node->name);
952         } else {
953             /* TODO use the BuildQName interface */
954             xmlChar *qname;
955
956             qname = xmlStrdup(node->ns->prefix);
957             qname = xmlStrcat(qname, BAD_CAST ":");
958             qname = xmlStrcat(qname, node->name);
959             reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
960                                     reader->ctxt->myDoc, node, qname);
961             if (qname != NULL)
962                 xmlFree(qname);
963         }
964     }
965 #endif /* LIBXML_VALID_ENABLED */
966 #ifdef LIBXML_SCHEMAS_ENABLED
967     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
968                (reader->rngValidCtxt != NULL)) {
969         int ret;
970
971         if (reader->rngFullNode != NULL) return;
972         ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
973                                             reader->ctxt->myDoc,
974                                             node);
975         if (ret == 0) {
976             /*
977              * this element requires a full tree
978              */
979             node = xmlTextReaderExpand(reader);
980             if (node == NULL) {
981 printf("Expand failed !\n");
982                 ret = -1;
983             } else {
984                 ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
985                                                     reader->ctxt->myDoc,
986                                                     node);
987                 reader->rngFullNode = node;
988             }
989         }
990         if (ret != 1)
991             reader->rngValidErrors++;
992     }
993 #endif
994 }
995
996 /**
997  * xmlTextReaderValidateCData:
998  * @reader:  the xmlTextReaderPtr used
999  * @data:  pointer to the CData
1000  * @len:  length of the CData block in bytes.
1001  *
1002  * Push some CData for validation
1003  */
1004 static void
1005 xmlTextReaderValidateCData(xmlTextReaderPtr reader,
1006                            const xmlChar *data, int len) {
1007 #ifdef LIBXML_VALID_ENABLED
1008     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1009         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1010         reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
1011                                                     data, len);
1012     }
1013 #endif /* LIBXML_VALID_ENABLED */
1014 #ifdef LIBXML_SCHEMAS_ENABLED
1015     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1016                (reader->rngValidCtxt != NULL)) {
1017         int ret;
1018
1019         if (reader->rngFullNode != NULL) return;
1020         ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
1021         if (ret != 1)
1022             reader->rngValidErrors++;
1023     }
1024 #endif
1025 }
1026
1027 /**
1028  * xmlTextReaderValidatePop:
1029  * @reader:  the xmlTextReaderPtr used
1030  *
1031  * Pop the current node from validation
1032  */
1033 static void
1034 xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
1035     xmlNodePtr node = reader->node;
1036
1037 #ifdef LIBXML_VALID_ENABLED
1038     if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
1039         (reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
1040         if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
1041             reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1042                                     reader->ctxt->myDoc, node, node->name);
1043         } else {
1044             /* TODO use the BuildQName interface */
1045             xmlChar *qname;
1046
1047             qname = xmlStrdup(node->ns->prefix);
1048             qname = xmlStrcat(qname, BAD_CAST ":");
1049             qname = xmlStrcat(qname, node->name);
1050             reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
1051                                     reader->ctxt->myDoc, node, qname);
1052             if (qname != NULL)
1053                 xmlFree(qname);
1054         }
1055     }
1056 #endif /* LIBXML_VALID_ENABLED */
1057 #ifdef LIBXML_SCHEMAS_ENABLED
1058     if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
1059                (reader->rngValidCtxt != NULL)) {
1060         int ret;
1061
1062         if (reader->rngFullNode != NULL) {
1063             if (node == reader->rngFullNode)
1064                 reader->rngFullNode = NULL;
1065             return;
1066         }
1067         ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
1068                                            reader->ctxt->myDoc,
1069                                            node);
1070         if (ret != 1)
1071             reader->rngValidErrors++;
1072     }
1073 #endif
1074 }
1075
1076 /**
1077  * xmlTextReaderValidateEntity:
1078  * @reader:  the xmlTextReaderPtr used
1079  *
1080  * Handle the validation when an entity reference is encountered and
1081  * entity substitution is not activated. As a result the parser interface
1082  * must walk through the entity and do the validation calls
1083  */
1084 static void
1085 xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
1086     xmlNodePtr oldnode = reader->node;
1087     xmlNodePtr node = reader->node;
1088     xmlParserCtxtPtr ctxt = reader->ctxt;
1089
1090     do {
1091         if (node->type == XML_ENTITY_REF_NODE) {
1092             /*
1093              * Case where the underlying tree is not availble, lookup the entity
1094              * and walk it.
1095              */
1096             if ((node->children == NULL) && (ctxt->sax != NULL) &&
1097                 (ctxt->sax->getEntity != NULL)) {
1098                 node->children = (xmlNodePtr)
1099                     ctxt->sax->getEntity(ctxt, node->name);
1100             }
1101
1102             if ((node->children != NULL) &&
1103                 (node->children->type == XML_ENTITY_DECL) &&
1104                 (node->children->children != NULL)) {
1105                 xmlTextReaderEntPush(reader, node);
1106                 node = node->children->children;
1107                 continue;
1108             } else {
1109                 /*
1110                  * The error has probably be raised already.
1111                  */
1112                 if (node == oldnode)
1113                     break;
1114                 node = node->next;
1115             }
1116 #ifdef LIBXML_REGEXP_ENABLED
1117         } else if (node->type == XML_ELEMENT_NODE) {
1118             reader->node = node;
1119             xmlTextReaderValidatePush(reader);
1120         } else if ((node->type == XML_TEXT_NODE) ||
1121                    (node->type == XML_CDATA_SECTION_NODE)) {
1122             xmlTextReaderValidateCData(reader, node->content,
1123                                        xmlStrlen(node->content));
1124 #endif
1125         }
1126
1127         /*
1128          * go to next node
1129          */
1130         if (node->children != NULL) {
1131             node = node->children;
1132             continue;
1133         } else if (node->type == XML_ELEMENT_NODE) {
1134             xmlTextReaderValidatePop(reader);
1135         }
1136         if (node->next != NULL) {
1137             node = node->next;
1138             continue;
1139         }
1140         do {
1141             node = node->parent;
1142             if (node->type == XML_ELEMENT_NODE) {
1143                 xmlNodePtr tmp;
1144                 if (reader->entNr == 0) {
1145                     while ((tmp = node->last) != NULL) {
1146                         if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1147                             xmlUnlinkNode(tmp);
1148                             xmlTextReaderFreeNode(reader, tmp);
1149                         } else
1150                             break;
1151                     }
1152                 }
1153                 reader->node = node;
1154                 xmlTextReaderValidatePop(reader);
1155             }
1156             if ((node->type == XML_ENTITY_DECL) &&
1157                 (reader->ent != NULL) && (reader->ent->children == node)) {
1158                 node = xmlTextReaderEntPop(reader);
1159             }
1160             if (node == oldnode)
1161                 break;
1162             if (node->next != NULL) {
1163                 node = node->next;
1164                 break;
1165             }
1166         } while ((node != NULL) && (node != oldnode));
1167     } while ((node != NULL) && (node != oldnode));
1168     reader->node = oldnode;
1169 }
1170 #endif /* LIBXML_REGEXP_ENABLED */
1171
1172
1173 /**
1174  * xmlTextReaderGetSuccessor:
1175  * @cur:  the current node
1176  *
1177  * Get the successor of a node if available.
1178  *
1179  * Returns the successor node or NULL
1180  */
1181 static xmlNodePtr
1182 xmlTextReaderGetSuccessor(xmlNodePtr cur) {
1183     if (cur == NULL) return(NULL) ; /* ERROR */
1184     if (cur->next != NULL) return(cur->next) ;
1185     do {
1186         cur = cur->parent;
1187         if (cur == NULL) break;
1188         if (cur->next != NULL) return(cur->next);
1189     } while (cur != NULL);
1190     return(cur);
1191 }
1192
1193 /**
1194  * xmlTextReaderDoExpand:
1195  * @reader:  the xmlTextReaderPtr used
1196  *
1197  * Makes sure that the current node is fully read as well as all its
1198  * descendant. It means the full DOM subtree must be available at the
1199  * end of the call.
1200  *
1201  * Returns 1 if the node was expanded successfully, 0 if there is no more
1202  *          nodes to read, or -1 in case of error
1203  */
1204 static int
1205 xmlTextReaderDoExpand(xmlTextReaderPtr reader) {
1206     int val;
1207
1208     if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL))
1209         return(-1);
1210     do {
1211         if (reader->ctxt->instate == XML_PARSER_EOF) return(1);
1212
1213         if (xmlTextReaderGetSuccessor(reader->node) != NULL)
1214             return(1);
1215         if (reader->ctxt->nodeNr < reader->depth)
1216             return(1);
1217         if (reader->mode == XML_TEXTREADER_MODE_EOF)
1218             return(1);
1219         val = xmlTextReaderPushData(reader);
1220         if (val < 0){
1221             reader->mode = XML_TEXTREADER_MODE_ERROR;
1222             return(-1);
1223         }
1224     } while(reader->mode != XML_TEXTREADER_MODE_EOF);
1225     return(1);
1226 }
1227
1228 /**
1229  * xmlTextReaderCollectSiblings:
1230  * @node:    the first child
1231  *
1232  *  Traverse depth-first through all sibling nodes and their children
1233  *  nodes and concatenate their content. This is an auxiliary function
1234  *  to xmlTextReaderReadString.
1235  *
1236  *  Returns a string containing the content, or NULL in case of error.
1237  */
1238 static xmlChar *
1239 xmlTextReaderCollectSiblings(xmlNodePtr node)
1240 {
1241     xmlBufferPtr buffer;
1242     xmlChar *ret;
1243
1244     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1245         return(NULL);
1246
1247     buffer = xmlBufferCreate();
1248     if (buffer == NULL)
1249        return NULL;
1250
1251     for ( ; node != NULL; node = node->next) {
1252        switch (node->type) {
1253        case XML_TEXT_NODE:
1254        case XML_CDATA_SECTION_NODE:
1255            xmlBufferCat(buffer, node->content);
1256            break;
1257        case XML_ELEMENT_NODE: {
1258            xmlChar *tmp;
1259
1260            tmp = xmlTextReaderCollectSiblings(node->children);
1261            xmlBufferCat(buffer, tmp);
1262            xmlFree(tmp);
1263            break;
1264        }
1265        default:
1266            break;
1267        }
1268     }
1269     ret = buffer->content;
1270     buffer->content = NULL;
1271     xmlBufferFree(buffer);
1272     return(ret);
1273 }
1274
1275 /**
1276  * xmlTextReaderRead:
1277  * @reader:  the xmlTextReaderPtr used
1278  *
1279  *  Moves the position of the current instance to the next node in
1280  *  the stream, exposing its properties.
1281  *
1282  *  Returns 1 if the node was read successfully, 0 if there is no more
1283  *          nodes to read, or -1 in case of error
1284  */
1285 int
1286 xmlTextReaderRead(xmlTextReaderPtr reader) {
1287     int val, olddepth = 0;
1288     xmlTextReaderState oldstate = XML_TEXTREADER_START;
1289     xmlNodePtr oldnode = NULL;
1290
1291
1292     if (reader == NULL)
1293         return(-1);
1294     reader->curnode = NULL;
1295     if (reader->doc != NULL)
1296         return(xmlTextReaderReadTree(reader));
1297     if (reader->ctxt == NULL)
1298         return(-1);
1299
1300 #ifdef DEBUG_READER
1301     fprintf(stderr, "\nREAD ");
1302     DUMP_READER
1303 #endif
1304     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
1305         reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
1306         /*
1307          * Initial state
1308          */
1309         do {
1310             val = xmlTextReaderPushData(reader);
1311                 if (val < 0){
1312                         reader->mode = XML_TEXTREADER_MODE_ERROR;
1313                         reader->state = XML_TEXTREADER_ERROR;
1314                 return(-1);
1315                 }
1316         } while ((reader->ctxt->node == NULL) &&
1317                  ((reader->mode != XML_TEXTREADER_MODE_EOF) &&
1318                   (reader->state != XML_TEXTREADER_DONE)));
1319         if (reader->ctxt->node == NULL) {
1320             if (reader->ctxt->myDoc != NULL) {
1321                 reader->node = reader->ctxt->myDoc->children;
1322             }
1323             if (reader->node == NULL){
1324                         reader->mode = XML_TEXTREADER_MODE_ERROR;
1325                         reader->state = XML_TEXTREADER_ERROR;
1326                 return(-1);
1327                 }
1328             reader->state = XML_TEXTREADER_ELEMENT;
1329         } else {
1330             if (reader->ctxt->myDoc != NULL) {
1331                 reader->node = reader->ctxt->myDoc->children;
1332             }
1333             if (reader->node == NULL)
1334                 reader->node = reader->ctxt->nodeTab[0];
1335             reader->state = XML_TEXTREADER_ELEMENT;
1336         }
1337         reader->depth = 0;
1338         reader->ctxt->parseMode = XML_PARSE_READER;
1339         goto node_found;
1340     }
1341     oldstate = reader->state;
1342     olddepth = reader->ctxt->nodeNr;
1343     oldnode = reader->node;
1344
1345 get_next_node:
1346     if (reader->node == NULL) {
1347         if (reader->mode == XML_TEXTREADER_MODE_EOF)
1348             return(0);
1349         else
1350             return(-1);
1351     }
1352
1353     /*
1354      * If we are not backtracking on ancestors or examined nodes,
1355      * that the parser didn't finished or that we arent at the end
1356      * of stream, continue processing.
1357      */
1358     while ((reader->node != NULL) && (reader->node->next == NULL) &&
1359            (reader->ctxt->nodeNr == olddepth) &&
1360            ((oldstate == XML_TEXTREADER_BACKTRACK) ||
1361             (reader->node->children == NULL) ||
1362             (reader->node->type == XML_ENTITY_REF_NODE) ||
1363             ((reader->node->children != NULL) &&
1364              (reader->node->children->type == XML_TEXT_NODE) &&
1365              (reader->node->children->next == NULL)) ||
1366             (reader->node->type == XML_DTD_NODE) ||
1367             (reader->node->type == XML_DOCUMENT_NODE) ||
1368             (reader->node->type == XML_HTML_DOCUMENT_NODE)) &&
1369            ((reader->ctxt->node == NULL) ||
1370             (reader->ctxt->node == reader->node) ||
1371             (reader->ctxt->node == reader->node->parent)) &&
1372            (reader->ctxt->instate != XML_PARSER_EOF)) {
1373         val = xmlTextReaderPushData(reader);
1374         if (val < 0){
1375                 reader->mode = XML_TEXTREADER_MODE_ERROR;
1376                 reader->state = XML_TEXTREADER_ERROR;
1377             return(-1);
1378         }
1379         if (reader->node == NULL)
1380             goto node_end;
1381     }
1382     if (oldstate != XML_TEXTREADER_BACKTRACK) {
1383         if ((reader->node->children != NULL) &&
1384             (reader->node->type != XML_ENTITY_REF_NODE) &&
1385             (reader->node->type != XML_XINCLUDE_START) &&
1386             (reader->node->type != XML_DTD_NODE)) {
1387             reader->node = reader->node->children;
1388             reader->depth++;
1389             reader->state = XML_TEXTREADER_ELEMENT;
1390             goto node_found;
1391         }
1392     }
1393     if (reader->node->next != NULL) {
1394         if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1395             (reader->node->type == XML_ELEMENT_NODE) &&
1396             (reader->node->children == NULL) &&
1397             ((reader->node->extra & NODE_IS_EMPTY) == 0)
1398 #ifdef LIBXML_XINCLUDE_ENABLED
1399             && (reader->in_xinclude <= 0)
1400 #endif
1401             ) {
1402             reader->state = XML_TEXTREADER_END;
1403             goto node_found;
1404         }
1405 #ifdef LIBXML_REGEXP_ENABLED
1406         if ((reader->validate) &&
1407             (reader->node->type == XML_ELEMENT_NODE))
1408             xmlTextReaderValidatePop(reader);
1409 #endif /* LIBXML_REGEXP_ENABLED */
1410         if ((reader->preserves > 0) &&
1411             (reader->node->extra & NODE_IS_SPRESERVED))
1412             reader->preserves--;
1413         reader->node = reader->node->next;
1414         reader->state = XML_TEXTREADER_ELEMENT;
1415
1416         /*
1417          * Cleanup of the old node
1418          */
1419         if ((reader->preserves == 0) &&
1420 #ifdef LIBXML_XINCLUDE_ENABLED
1421             (reader->in_xinclude == 0) &&
1422 #endif
1423             (reader->entNr == 0) &&
1424             (reader->node->prev != NULL) &&
1425             (reader->node->prev->type != XML_DTD_NODE)) {
1426             xmlNodePtr tmp = reader->node->prev;
1427             if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
1428                 xmlUnlinkNode(tmp);
1429                 xmlTextReaderFreeNode(reader, tmp);
1430             }
1431         }
1432
1433         goto node_found;
1434     }
1435     if ((oldstate == XML_TEXTREADER_ELEMENT) &&
1436         (reader->node->type == XML_ELEMENT_NODE) &&
1437         (reader->node->children == NULL) &&
1438         ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
1439         reader->state = XML_TEXTREADER_END;
1440         goto node_found;
1441     }
1442 #ifdef LIBXML_REGEXP_ENABLED
1443     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE))
1444         xmlTextReaderValidatePop(reader);
1445 #endif /* LIBXML_REGEXP_ENABLED */
1446     if ((reader->preserves > 0) &&
1447         (reader->node->extra & NODE_IS_SPRESERVED))
1448         reader->preserves--;
1449     reader->node = reader->node->parent;
1450     if ((reader->node == NULL) ||
1451         (reader->node->type == XML_DOCUMENT_NODE) ||
1452 #ifdef LIBXML_DOCB_ENABLED
1453         (reader->node->type == XML_DOCB_DOCUMENT_NODE) ||
1454 #endif
1455         (reader->node->type == XML_HTML_DOCUMENT_NODE)) {
1456         if (reader->mode != XML_TEXTREADER_MODE_EOF) {
1457             val = xmlParseChunk(reader->ctxt, "", 0, 1);
1458             reader->state = XML_TEXTREADER_DONE;
1459             if (val != 0)
1460                 return(-1);
1461         }
1462         reader->node = NULL;
1463         reader->depth = -1;
1464
1465         /*
1466          * Cleanup of the old node
1467          */
1468         if ((oldnode != NULL) && (reader->preserves == 0) &&
1469 #ifdef LIBXML_XINCLUDE_ENABLED
1470             (reader->in_xinclude == 0) &&
1471 #endif
1472             (reader->entNr == 0) &&
1473             (oldnode->type != XML_DTD_NODE) &&
1474             ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
1475             xmlUnlinkNode(oldnode);
1476             xmlTextReaderFreeNode(reader, oldnode);
1477         }
1478
1479         goto node_end;
1480     }
1481     if ((reader->preserves == 0) &&
1482 #ifdef LIBXML_XINCLUDE_ENABLED
1483         (reader->in_xinclude == 0) &&
1484 #endif
1485         (reader->entNr == 0) &&
1486         (reader->node->last != NULL) &&
1487         ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
1488         xmlNodePtr tmp = reader->node->last;
1489         xmlUnlinkNode(tmp);
1490         xmlTextReaderFreeNode(reader, tmp);
1491     }
1492     reader->depth--;
1493     reader->state = XML_TEXTREADER_BACKTRACK;
1494
1495 node_found:
1496     DUMP_READER
1497
1498     /*
1499      * If we are in the middle of a piece of CDATA make sure it's finished
1500      */
1501     if ((reader->node != NULL) &&
1502         (reader->node->next == NULL) &&
1503         ((reader->node->type == XML_TEXT_NODE) ||
1504          (reader->node->type == XML_CDATA_SECTION_NODE))) {
1505             if (xmlTextReaderExpand(reader) == NULL)
1506                 return -1;
1507     }
1508
1509 #ifdef LIBXML_XINCLUDE_ENABLED
1510     /*
1511      * Handle XInclude if asked for
1512      */
1513     if ((reader->xinclude) && (reader->node != NULL) &&
1514         (reader->node->type == XML_ELEMENT_NODE) &&
1515         (reader->node->ns != NULL) &&
1516         ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
1517          (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) {
1518         if (reader->xincctxt == NULL) {
1519             reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc);
1520             xmlXIncludeSetFlags(reader->xincctxt,
1521                                 reader->parserFlags & (~XML_PARSE_NOXINCNODE));
1522         }
1523         /*
1524          * expand that node and process it
1525          */
1526         if (xmlTextReaderExpand(reader) == NULL)
1527             return -1;
1528         xmlXIncludeProcessNode(reader->xincctxt, reader->node);
1529     }
1530     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) {
1531         reader->in_xinclude++;
1532         goto get_next_node;
1533     }
1534     if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_END)) {
1535         reader->in_xinclude--;
1536         goto get_next_node;
1537     }
1538 #endif
1539     /*
1540      * Handle entities enter and exit when in entity replacement mode
1541      */
1542     if ((reader->node != NULL) &&
1543         (reader->node->type == XML_ENTITY_REF_NODE) &&
1544         (reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
1545         /*
1546          * Case where the underlying tree is not availble, lookup the entity
1547          * and walk it.
1548          */
1549         if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
1550             (reader->ctxt->sax->getEntity != NULL)) {
1551             reader->node->children = (xmlNodePtr)
1552                 reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
1553         }
1554
1555         if ((reader->node->children != NULL) &&
1556             (reader->node->children->type == XML_ENTITY_DECL) &&
1557             (reader->node->children->children != NULL)) {
1558             xmlTextReaderEntPush(reader, reader->node);
1559             reader->node = reader->node->children->children;
1560         }
1561 #ifdef LIBXML_REGEXP_ENABLED
1562     } else if ((reader->node != NULL) &&
1563                (reader->node->type == XML_ENTITY_REF_NODE) &&
1564                (reader->ctxt != NULL) && (reader->validate)) {
1565         xmlTextReaderValidateEntity(reader);
1566 #endif /* LIBXML_REGEXP_ENABLED */
1567     }
1568     if ((reader->node != NULL) &&
1569         (reader->node->type == XML_ENTITY_DECL) &&
1570         (reader->ent != NULL) && (reader->ent->children == reader->node)) {
1571         reader->node = xmlTextReaderEntPop(reader);
1572         reader->depth++;
1573         goto get_next_node;
1574     }
1575 #ifdef LIBXML_REGEXP_ENABLED
1576     if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node != NULL)) {
1577         xmlNodePtr node = reader->node;
1578
1579         if ((node->type == XML_ELEMENT_NODE) &&
1580             ((reader->state != XML_TEXTREADER_END) &&
1581              (reader->state != XML_TEXTREADER_BACKTRACK))) {
1582             xmlTextReaderValidatePush(reader);
1583         } else if ((node->type == XML_TEXT_NODE) ||
1584                    (node->type == XML_CDATA_SECTION_NODE)) {
1585             xmlTextReaderValidateCData(reader, node->content,
1586                                        xmlStrlen(node->content));
1587         }
1588     }
1589 #endif /* LIBXML_REGEXP_ENABLED */
1590 #ifdef LIBXML_PATTERN_ENABLED
1591     if ((reader->patternNr > 0) && (reader->state != XML_TEXTREADER_END) &&
1592         (reader->state != XML_TEXTREADER_BACKTRACK)) {
1593         int i;
1594         for (i = 0;i < reader->patternNr;i++) {
1595              if (xmlPatternMatch(reader->patternTab[i], reader->node) == 1) {
1596                  xmlTextReaderPreserve(reader);
1597                  break;
1598              }
1599         }
1600     }
1601 #endif /* LIBXML_PATTERN_ENABLED */
1602 #ifdef LIBXML_SCHEMAS_ENABLED
1603     if ((reader->validate == XML_TEXTREADER_VALIDATE_XSD) &&
1604         (reader->xsdValidErrors == 0) &&
1605         (reader->xsdValidCtxt != NULL)) {
1606         reader->xsdValidErrors = !xmlSchemaIsValid(reader->xsdValidCtxt);
1607     }
1608 #endif /* LIBXML_PATTERN_ENABLED */
1609     return(1);
1610 node_end:
1611     reader->state = XML_TEXTREADER_DONE;
1612     return(0);
1613 }
1614
1615 /**
1616  * xmlTextReaderReadState:
1617  * @reader:  the xmlTextReaderPtr used
1618  *
1619  * Gets the read state of the reader.
1620  *
1621  * Returns the state value, or -1 in case of error
1622  */
1623 int
1624 xmlTextReaderReadState(xmlTextReaderPtr reader) {
1625     if (reader == NULL)
1626         return(-1);
1627     return(reader->mode);
1628 }
1629
1630 /**
1631  * xmlTextReaderExpand:
1632  * @reader:  the xmlTextReaderPtr used
1633  *
1634  * Reads the contents of the current node and the full subtree. It then makes
1635  * the subtree available until the next xmlTextReaderRead() call
1636  *
1637  * Returns a node pointer valid until the next xmlTextReaderRead() call
1638  *         or NULL in case of error.
1639  */
1640 xmlNodePtr
1641 xmlTextReaderExpand(xmlTextReaderPtr reader) {
1642     if ((reader == NULL) || (reader->node == NULL))
1643         return(NULL);
1644     if (reader->doc != NULL)
1645         return(reader->node);
1646     if (reader->ctxt == NULL)
1647         return(NULL);
1648     if (xmlTextReaderDoExpand(reader) < 0)
1649         return(NULL);
1650     return(reader->node);
1651 }
1652
1653 /**
1654  * xmlTextReaderNext:
1655  * @reader:  the xmlTextReaderPtr used
1656  *
1657  * Skip to the node following the current one in document order while
1658  * avoiding the subtree if any.
1659  *
1660  * Returns 1 if the node was read successfully, 0 if there is no more
1661  *          nodes to read, or -1 in case of error
1662  */
1663 int
1664 xmlTextReaderNext(xmlTextReaderPtr reader) {
1665     int ret;
1666     xmlNodePtr cur;
1667
1668     if (reader == NULL)
1669         return(-1);
1670     if (reader->doc != NULL)
1671         return(xmlTextReaderNextTree(reader));
1672     cur = reader->node;
1673     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1674         return(xmlTextReaderRead(reader));
1675     if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
1676         return(xmlTextReaderRead(reader));
1677     if (cur->extra & NODE_IS_EMPTY)
1678         return(xmlTextReaderRead(reader));
1679     do {
1680         ret = xmlTextReaderRead(reader);
1681         if (ret != 1)
1682             return(ret);
1683     } while (reader->node != cur);
1684     return(xmlTextReaderRead(reader));
1685 }
1686
1687 #ifdef LIBXML_WRITER_ENABLED
1688 /**
1689  * xmlTextReaderReadInnerXml:
1690  * @reader:  the xmlTextReaderPtr used
1691  *
1692  * Reads the contents of the current node, including child nodes and markup.
1693  *
1694  * Returns a string containing the XML content, or NULL if the current node
1695  *         is neither an element nor attribute, or has no child nodes. The
1696  *         string must be deallocated by the caller.
1697  */
1698 xmlChar *
1699 xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1700 {
1701     xmlChar *resbuf;
1702     xmlNodePtr node, cur_node;
1703     xmlBufferPtr buff, buff2;
1704     xmlDocPtr doc;
1705
1706     if (xmlTextReaderExpand(reader) == NULL) {
1707         return NULL;
1708     }
1709     doc = reader->doc;
1710     buff = xmlBufferCreate();
1711     for (cur_node = reader->node->children; cur_node != NULL;
1712          cur_node = cur_node->next) {
1713         node = xmlDocCopyNode(cur_node, doc, 1);
1714         buff2 = xmlBufferCreate();
1715         if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) {
1716             xmlFreeNode(node);
1717             xmlBufferFree(buff2);
1718             xmlBufferFree(buff);
1719             return NULL;
1720         }
1721         xmlBufferCat(buff, buff2->content);
1722         xmlFreeNode(node);
1723         xmlBufferFree(buff2);
1724     }
1725     resbuf = buff->content;
1726     buff->content = NULL;
1727
1728     xmlBufferFree(buff);
1729     return resbuf;
1730 }
1731 #endif
1732
1733 #ifdef LIBXML_WRITER_ENABLED
1734 /**
1735  * xmlTextReaderReadOuterXml:
1736  * @reader:  the xmlTextReaderPtr used
1737  *
1738  * Reads the contents of the current node, including child nodes and markup.
1739  *
1740  * Returns a string containing the node and any XML content, or NULL if the
1741  *         current node cannot be serialized. The string must be deallocated
1742  *         by the caller.
1743  */
1744 xmlChar *
1745 xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
1746 {
1747     xmlChar *resbuf;
1748     xmlNodePtr node;
1749     xmlBufferPtr buff;
1750     xmlDocPtr doc;
1751
1752     node = reader->node;
1753     doc = reader->doc;
1754     if (xmlTextReaderExpand(reader) == NULL) {
1755         return NULL;
1756     }
1757         if (node->type == XML_DTD_NODE) {
1758                 node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node);
1759         } else {
1760                 node = xmlDocCopyNode(node, doc, 1);
1761         }
1762     buff = xmlBufferCreate();
1763     if (xmlNodeDump(buff, doc, node, 0, 0) == -1) {
1764         xmlFreeNode(node);
1765         xmlBufferFree(buff);
1766         return NULL;
1767     }
1768
1769     resbuf = buff->content;
1770     buff->content = NULL;
1771
1772     xmlFreeNode(node);
1773     xmlBufferFree(buff);
1774     return resbuf;
1775 }
1776 #endif
1777
1778 /**
1779  * xmlTextReaderReadString:
1780  * @reader:  the xmlTextReaderPtr used
1781  *
1782  * Reads the contents of an element or a text node as a string.
1783  *
1784  * Returns a string containing the contents of the Element or Text node,
1785  *         or NULL if the reader is positioned on any other type of node.
1786  *         The string must be deallocated by the caller.
1787  */
1788 xmlChar *
1789 xmlTextReaderReadString(xmlTextReaderPtr reader)
1790 {
1791     xmlNodePtr node;
1792
1793     if ((reader == NULL) || (reader->node == NULL))
1794        return(NULL);
1795
1796     node = (reader->curnode != NULL) ? reader->curnode : reader->node;
1797     switch (node->type) {
1798     case XML_TEXT_NODE:
1799        if (node->content != NULL)
1800            return(xmlStrdup(node->content));
1801        break;
1802     case XML_ELEMENT_NODE:
1803         if (xmlTextReaderDoExpand(reader) != -1) {
1804             return xmlTextReaderCollectSiblings(node->children);
1805         }
1806         break;
1807     case XML_ATTRIBUTE_NODE:
1808         TODO
1809         break;
1810     default:
1811        break;
1812     }
1813     return(NULL);
1814 }
1815
1816 #if 0
1817 /**
1818  * xmlTextReaderReadBase64:
1819  * @reader:  the xmlTextReaderPtr used
1820  * @array:  a byte array to store the content.
1821  * @offset:  the zero-based index into array where the method should
1822  *           begin to write.
1823  * @len:  the number of bytes to write.
1824  *
1825  * Reads and decodes the Base64 encoded contents of an element and
1826  * stores the result in a byte buffer.
1827  *
1828  * Returns the number of bytes written to array, or zero if the current
1829  *         instance is not positioned on an element or -1 in case of error.
1830  */
1831 int
1832 xmlTextReaderReadBase64(xmlTextReaderPtr reader,
1833                         unsigned char *array ATTRIBUTE_UNUSED,
1834                         int offset ATTRIBUTE_UNUSED,
1835                         int len ATTRIBUTE_UNUSED) {
1836     if ((reader == NULL) || (reader->ctxt == NULL))
1837         return(-1);
1838     if (reader->ctxt->wellFormed != 1)
1839         return(-1);
1840
1841     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1842         return(0);
1843     TODO
1844     return(0);
1845 }
1846
1847 /**
1848  * xmlTextReaderReadBinHex:
1849  * @reader:  the xmlTextReaderPtr used
1850  * @array:  a byte array to store the content.
1851  * @offset:  the zero-based index into array where the method should
1852  *           begin to write.
1853  * @len:  the number of bytes to write.
1854  *
1855  * Reads and decodes the BinHex encoded contents of an element and
1856  * stores the result in a byte buffer.
1857  *
1858  * Returns the number of bytes written to array, or zero if the current
1859  *         instance is not positioned on an element or -1 in case of error.
1860  */
1861 int
1862 xmlTextReaderReadBinHex(xmlTextReaderPtr reader,
1863                         unsigned char *array ATTRIBUTE_UNUSED,
1864                         int offset ATTRIBUTE_UNUSED,
1865                         int len ATTRIBUTE_UNUSED) {
1866     if ((reader == NULL) || (reader->ctxt == NULL))
1867         return(-1);
1868     if (reader->ctxt->wellFormed != 1)
1869         return(-1);
1870
1871     if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
1872         return(0);
1873     TODO
1874     return(0);
1875 }
1876 #endif
1877
1878 /************************************************************************
1879  *                                                                      *
1880  *                      Operating on a preparsed tree                   *
1881  *                                                                      *
1882  ************************************************************************/
1883 static int
1884 xmlTextReaderNextTree(xmlTextReaderPtr reader)
1885 {
1886     if (reader == NULL)
1887         return(-1);
1888
1889     if (reader->state == XML_TEXTREADER_END)
1890         return(0);
1891
1892     if (reader->node == NULL) {
1893         if (reader->doc->children == NULL) {
1894             reader->state = XML_TEXTREADER_END;
1895             return(0);
1896         }
1897
1898         reader->node = reader->doc->children;
1899         reader->state = XML_TEXTREADER_START;
1900         return(1);
1901     }
1902
1903     if (reader->state != XML_TEXTREADER_BACKTRACK) {
1904         /* Here removed traversal to child, because we want to skip the subtree,
1905         replace with traversal to sibling to skip subtree */
1906         if (reader->node->next != 0) {
1907             /* Move to sibling if present,skipping sub-tree */
1908             reader->node = reader->node->next;
1909             reader->state = XML_TEXTREADER_START;
1910             return(1);
1911         }
1912
1913         /* if reader->node->next is NULL mean no subtree for current node,
1914         so need to move to sibling of parent node if present */
1915         if ((reader->node->type == XML_ELEMENT_NODE) ||
1916             (reader->node->type == XML_ATTRIBUTE_NODE)) {
1917             reader->state = XML_TEXTREADER_BACKTRACK;
1918             /* This will move to parent if present */
1919             xmlTextReaderRead(reader);
1920         }
1921     }
1922
1923     if (reader->node->next != 0) {
1924         reader->node = reader->node->next;
1925         reader->state = XML_TEXTREADER_START;
1926         return(1);
1927     }
1928
1929     if (reader->node->parent != 0) {
1930         if (reader->node->parent->type == XML_DOCUMENT_NODE) {
1931             reader->state = XML_TEXTREADER_END;
1932             return(0);
1933         }
1934
1935         reader->node = reader->node->parent;
1936         reader->depth--;
1937         reader->state = XML_TEXTREADER_BACKTRACK;
1938         /* Repeat process to move to sibling of parent node if present */
1939         xmlTextReaderNextTree(reader);
1940     }
1941
1942     reader->state = XML_TEXTREADER_END;
1943
1944     return(1);
1945 }
1946
1947 /**
1948  * xmlTextReaderReadTree:
1949  * @reader:  the xmlTextReaderPtr used
1950  *
1951  *  Moves the position of the current instance to the next node in
1952  *  the stream, exposing its properties.
1953  *
1954  *  Returns 1 if the node was read successfully, 0 if there is no more
1955  *          nodes to read, or -1 in case of error
1956  */
1957 static int
1958 xmlTextReaderReadTree(xmlTextReaderPtr reader) {
1959     if (reader->state == XML_TEXTREADER_END)
1960         return(0);
1961
1962 next_node:
1963     if (reader->node == NULL) {
1964         if (reader->doc->children == NULL) {
1965             reader->state = XML_TEXTREADER_END;
1966             return(0);
1967         }
1968
1969         reader->node = reader->doc->children;
1970         reader->state = XML_TEXTREADER_START;
1971         goto found_node;
1972     }
1973
1974     if ((reader->state != XML_TEXTREADER_BACKTRACK) &&
1975         (reader->node->type != XML_DTD_NODE) &&
1976         (reader->node->type != XML_XINCLUDE_START) &&
1977         (reader->node->type != XML_ENTITY_REF_NODE)) {
1978         if (reader->node->children != NULL) {
1979             reader->node = reader->node->children;
1980             reader->depth++;
1981             reader->state = XML_TEXTREADER_START;
1982             goto found_node;
1983         }
1984
1985         if (reader->node->type == XML_ATTRIBUTE_NODE) {
1986             reader->state = XML_TEXTREADER_BACKTRACK;
1987             goto found_node;
1988         }
1989     }
1990
1991     if (reader->node->next != NULL) {
1992         reader->node = reader->node->next;
1993         reader->state = XML_TEXTREADER_START;
1994         goto found_node;
1995     }
1996
1997     if (reader->node->parent != NULL) {
1998         if ((reader->node->parent->type == XML_DOCUMENT_NODE) ||
1999             (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) {
2000             reader->state = XML_TEXTREADER_END;
2001             return(0);
2002         }
2003
2004         reader->node = reader->node->parent;
2005         reader->depth--;
2006         reader->state = XML_TEXTREADER_BACKTRACK;
2007         goto found_node;
2008     }
2009
2010     reader->state = XML_TEXTREADER_END;
2011
2012 found_node:
2013     if ((reader->node->type == XML_XINCLUDE_START) ||
2014         (reader->node->type == XML_XINCLUDE_END))
2015         goto next_node;
2016
2017     return(1);
2018 }
2019
2020 /**
2021  * xmlTextReaderNextSibling:
2022  * @reader:  the xmlTextReaderPtr used
2023  *
2024  * Skip to the node following the current one in document order while
2025  * avoiding the subtree if any.
2026  * Currently implemented only for Readers built on a document
2027  *
2028  * Returns 1 if the node was read successfully, 0 if there is no more
2029  *          nodes to read, or -1 in case of error
2030  */
2031 int
2032 xmlTextReaderNextSibling(xmlTextReaderPtr reader) {
2033     if (reader == NULL)
2034         return(-1);
2035     if (reader->doc == NULL) {
2036         /* TODO */
2037         return(-1);
2038     }
2039
2040     if (reader->state == XML_TEXTREADER_END)
2041         return(0);
2042
2043     if (reader->node == NULL)
2044         return(xmlTextReaderNextTree(reader));
2045
2046     if (reader->node->next != NULL) {
2047         reader->node = reader->node->next;
2048         reader->state = XML_TEXTREADER_START;
2049         return(1);
2050     }
2051
2052     return(0);
2053 }
2054
2055 /************************************************************************
2056  *                                                                      *
2057  *                      Constructor and destructors                     *
2058  *                                                                      *
2059  ************************************************************************/
2060 /**
2061  * xmlNewTextReader:
2062  * @input: the xmlParserInputBufferPtr used to read data
2063  * @URI: the URI information for the source if available
2064  *
2065  * Create an xmlTextReader structure fed with @input
2066  *
2067  * Returns the new xmlTextReaderPtr or NULL in case of error
2068  */
2069 xmlTextReaderPtr
2070 xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
2071     xmlTextReaderPtr ret;
2072
2073     if (input == NULL)
2074         return(NULL);
2075     ret = xmlMalloc(sizeof(xmlTextReader));
2076     if (ret == NULL) {
2077         xmlGenericError(xmlGenericErrorContext,
2078                 "xmlNewTextReader : malloc failed\n");
2079         return(NULL);
2080     }
2081     memset(ret, 0, sizeof(xmlTextReader));
2082     ret->doc = NULL;
2083     ret->entTab = NULL;
2084     ret->entMax = 0;
2085     ret->entNr = 0;
2086     ret->input = input;
2087     ret->buffer = xmlBufCreateSize(100);
2088     if (ret->buffer == NULL) {
2089         xmlFree(ret);
2090         xmlGenericError(xmlGenericErrorContext,
2091                 "xmlNewTextReader : malloc failed\n");
2092         return(NULL);
2093     }
2094     /* no operation on a reader should require a huge buffer */
2095     xmlBufSetAllocationScheme(ret->buffer,
2096                               XML_BUFFER_ALLOC_BOUNDED);
2097     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
2098     if (ret->sax == NULL) {
2099         xmlBufFree(ret->buffer);
2100         xmlFree(ret);
2101         xmlGenericError(xmlGenericErrorContext,
2102                 "xmlNewTextReader : malloc failed\n");
2103         return(NULL);
2104     }
2105     xmlSAXVersion(ret->sax, 2);
2106     ret->startElement = ret->sax->startElement;
2107     ret->sax->startElement = xmlTextReaderStartElement;
2108     ret->endElement = ret->sax->endElement;
2109     ret->sax->endElement = xmlTextReaderEndElement;
2110 #ifdef LIBXML_SAX1_ENABLED
2111     if (ret->sax->initialized == XML_SAX2_MAGIC) {
2112 #endif /* LIBXML_SAX1_ENABLED */
2113         ret->startElementNs = ret->sax->startElementNs;
2114         ret->sax->startElementNs = xmlTextReaderStartElementNs;
2115         ret->endElementNs = ret->sax->endElementNs;
2116         ret->sax->endElementNs = xmlTextReaderEndElementNs;
2117 #ifdef LIBXML_SAX1_ENABLED
2118     } else {
2119         ret->startElementNs = NULL;
2120         ret->endElementNs = NULL;
2121     }
2122 #endif /* LIBXML_SAX1_ENABLED */
2123     ret->characters = ret->sax->characters;
2124     ret->sax->characters = xmlTextReaderCharacters;
2125     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;
2126     ret->cdataBlock = ret->sax->cdataBlock;
2127     ret->sax->cdataBlock = xmlTextReaderCDataBlock;
2128
2129     ret->mode = XML_TEXTREADER_MODE_INITIAL;
2130     ret->node = NULL;
2131     ret->curnode = NULL;
2132     if (xmlBufUse(ret->input->buffer) < 4) {
2133         xmlParserInputBufferRead(input, 4);
2134     }
2135     if (xmlBufUse(ret->input->buffer) >= 4) {
2136         ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
2137                              (const char *) xmlBufContent(ret->input->buffer),
2138                                             4, URI);
2139         ret->base = 0;
2140         ret->cur = 4;
2141     } else {
2142         ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL, NULL, 0, URI);
2143         ret->base = 0;
2144         ret->cur = 0;
2145     }
2146
2147     if (ret->ctxt == NULL) {
2148         xmlGenericError(xmlGenericErrorContext,
2149                 "xmlNewTextReader : malloc failed\n");
2150         xmlBufFree(ret->buffer);
2151         xmlFree(ret->sax);
2152         xmlFree(ret);
2153         return(NULL);
2154     }
2155     ret->ctxt->parseMode = XML_PARSE_READER;
2156     ret->ctxt->_private = ret;
2157     ret->ctxt->linenumbers = 1;
2158     ret->ctxt->dictNames = 1;
2159     ret->allocs = XML_TEXTREADER_CTXT;
2160     /*
2161      * use the parser dictionary to allocate all elements and attributes names
2162      */
2163     ret->ctxt->docdict = 1;
2164     ret->dict = ret->ctxt->dict;
2165 #ifdef LIBXML_XINCLUDE_ENABLED
2166     ret->xinclude = 0;
2167 #endif
2168 #ifdef LIBXML_PATTERN_ENABLED
2169     ret->patternMax = 0;
2170     ret->patternTab = NULL;
2171 #endif
2172     return(ret);
2173 }
2174
2175 /**
2176  * xmlNewTextReaderFilename:
2177  * @URI: the URI of the resource to process
2178  *
2179  * Create an xmlTextReader structure fed with the resource at @URI
2180  *
2181  * Returns the new xmlTextReaderPtr or NULL in case of error
2182  */
2183 xmlTextReaderPtr
2184 xmlNewTextReaderFilename(const char *URI) {
2185     xmlParserInputBufferPtr input;
2186     xmlTextReaderPtr ret;
2187     char *directory = NULL;
2188
2189     input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE);
2190     if (input == NULL)
2191         return(NULL);
2192     ret = xmlNewTextReader(input, URI);
2193     if (ret == NULL) {
2194         xmlFreeParserInputBuffer(input);
2195         return(NULL);
2196     }
2197     ret->allocs |= XML_TEXTREADER_INPUT;
2198     if (ret->ctxt->directory == NULL)
2199         directory = xmlParserGetDirectory(URI);
2200     if ((ret->ctxt->directory == NULL) && (directory != NULL))
2201         ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
2202     if (directory != NULL)
2203         xmlFree(directory);
2204     return(ret);
2205 }
2206
2207 /**
2208  * xmlFreeTextReader:
2209  * @reader:  the xmlTextReaderPtr
2210  *
2211  * Deallocate all the resources associated to the reader
2212  */
2213 void
2214 xmlFreeTextReader(xmlTextReaderPtr reader) {
2215     if (reader == NULL)
2216         return;
2217 #ifdef LIBXML_SCHEMAS_ENABLED
2218     if (reader->rngSchemas != NULL) {
2219         xmlRelaxNGFree(reader->rngSchemas);
2220         reader->rngSchemas = NULL;
2221     }
2222     if (reader->rngValidCtxt != NULL) {
2223         if (! reader->rngPreserveCtxt)
2224             xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
2225         reader->rngValidCtxt = NULL;
2226     }
2227     if (reader->xsdPlug != NULL) {
2228         xmlSchemaSAXUnplug(reader->xsdPlug);
2229         reader->xsdPlug = NULL;
2230     }
2231     if (reader->xsdValidCtxt != NULL) {
2232         if (! reader->xsdPreserveCtxt)
2233             xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
2234         reader->xsdValidCtxt = NULL;
2235     }
2236     if (reader->xsdSchemas != NULL) {
2237         xmlSchemaFree(reader->xsdSchemas);
2238         reader->xsdSchemas = NULL;
2239     }
2240 #endif
2241 #ifdef LIBXML_XINCLUDE_ENABLED
2242     if (reader->xincctxt != NULL)
2243         xmlXIncludeFreeContext(reader->xincctxt);
2244 #endif
2245 #ifdef LIBXML_PATTERN_ENABLED
2246     if (reader->patternTab != NULL) {
2247         int i;
2248         for (i = 0;i < reader->patternNr;i++) {
2249             if (reader->patternTab[i] != NULL)
2250                 xmlFreePattern(reader->patternTab[i]);
2251         }
2252         xmlFree(reader->patternTab);
2253     }
2254 #endif
2255     if (reader->faketext != NULL) {
2256         xmlFreeNode(reader->faketext);
2257     }
2258     if (reader->ctxt != NULL) {
2259         if (reader->dict == reader->ctxt->dict)
2260             reader->dict = NULL;
2261         if (reader->ctxt->myDoc != NULL) {
2262             if (reader->preserve == 0)
2263                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2264             reader->ctxt->myDoc = NULL;
2265         }
2266         if ((reader->ctxt->vctxt.vstateTab != NULL) &&
2267             (reader->ctxt->vctxt.vstateMax > 0)){
2268             xmlFree(reader->ctxt->vctxt.vstateTab);
2269             reader->ctxt->vctxt.vstateTab = NULL;
2270             reader->ctxt->vctxt.vstateMax = 0;
2271         }
2272         if (reader->allocs & XML_TEXTREADER_CTXT)
2273             xmlFreeParserCtxt(reader->ctxt);
2274     }
2275     if (reader->sax != NULL)
2276         xmlFree(reader->sax);
2277     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
2278         xmlFreeParserInputBuffer(reader->input);
2279     if (reader->buffer != NULL)
2280         xmlBufFree(reader->buffer);
2281     if (reader->entTab != NULL)
2282         xmlFree(reader->entTab);
2283     if (reader->dict != NULL)
2284         xmlDictFree(reader->dict);
2285     xmlFree(reader);
2286 }
2287
2288 /************************************************************************
2289  *                                                                      *
2290  *                      Methods for XmlTextReader                       *
2291  *                                                                      *
2292  ************************************************************************/
2293 /**
2294  * xmlTextReaderClose:
2295  * @reader:  the xmlTextReaderPtr used
2296  *
2297  * This method releases any resources allocated by the current instance
2298  * changes the state to Closed and close any underlying input.
2299  *
2300  * Returns 0 or -1 in case of error
2301  */
2302 int
2303 xmlTextReaderClose(xmlTextReaderPtr reader) {
2304     if (reader == NULL)
2305         return(-1);
2306     reader->node = NULL;
2307     reader->curnode = NULL;
2308     reader->mode = XML_TEXTREADER_MODE_CLOSED;
2309     if (reader->ctxt != NULL) {
2310         xmlStopParser(reader->ctxt);
2311         if (reader->ctxt->myDoc != NULL) {
2312             if (reader->preserve == 0)
2313                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2314             reader->ctxt->myDoc = NULL;
2315         }
2316     }
2317     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT)) {
2318         xmlFreeParserInputBuffer(reader->input);
2319         reader->allocs -= XML_TEXTREADER_INPUT;
2320     }
2321     return(0);
2322 }
2323
2324 /**
2325  * xmlTextReaderGetAttributeNo:
2326  * @reader:  the xmlTextReaderPtr used
2327  * @no: the zero-based index of the attribute relative to the containing element
2328  *
2329  * Provides the value of the attribute with the specified index relative
2330  * to the containing element.
2331  *
2332  * Returns a string containing the value of the specified attribute, or NULL
2333  *    in case of error. The string must be deallocated by the caller.
2334  */
2335 xmlChar *
2336 xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
2337     xmlChar *ret;
2338     int i;
2339     xmlAttrPtr cur;
2340     xmlNsPtr ns;
2341
2342     if (reader == NULL)
2343         return(NULL);
2344     if (reader->node == NULL)
2345         return(NULL);
2346     if (reader->curnode != NULL)
2347         return(NULL);
2348     /* TODO: handle the xmlDecl */
2349     if (reader->node->type != XML_ELEMENT_NODE)
2350         return(NULL);
2351
2352     ns = reader->node->nsDef;
2353     for (i = 0;(i < no) && (ns != NULL);i++) {
2354         ns = ns->next;
2355     }
2356     if (ns != NULL)
2357         return(xmlStrdup(ns->href));
2358
2359     cur = reader->node->properties;
2360     if (cur == NULL)
2361         return(NULL);
2362     for (;i < no;i++) {
2363         cur = cur->next;
2364         if (cur == NULL)
2365             return(NULL);
2366     }
2367     /* TODO walk the DTD if present */
2368
2369     ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
2370     if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2371     return(ret);
2372 }
2373
2374 /**
2375  * xmlTextReaderGetAttribute:
2376  * @reader:  the xmlTextReaderPtr used
2377  * @name: the qualified name of the attribute.
2378  *
2379  * Provides the value of the attribute with the specified qualified name.
2380  *
2381  * Returns a string containing the value of the specified attribute, or NULL
2382  *    in case of error. The string must be deallocated by the caller.
2383  */
2384 xmlChar *
2385 xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2386     xmlChar *prefix = NULL;
2387     xmlChar *localname;
2388     xmlNsPtr ns;
2389     xmlChar *ret = NULL;
2390
2391     if ((reader == NULL) || (name == NULL))
2392         return(NULL);
2393     if (reader->node == NULL)
2394         return(NULL);
2395     if (reader->curnode != NULL)
2396         return(NULL);
2397
2398     /* TODO: handle the xmlDecl */
2399     if (reader->node->type != XML_ELEMENT_NODE)
2400         return(NULL);
2401
2402     localname = xmlSplitQName2(name, &prefix);
2403     if (localname == NULL) {
2404                 /*
2405                  * Namespace default decl
2406                  */
2407                 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2408                         ns = reader->node->nsDef;
2409                         while (ns != NULL) {
2410                                 if (ns->prefix == NULL) {
2411                                         return(xmlStrdup(ns->href));
2412                                 }
2413                                 ns = ns->next;
2414                         }
2415                         return NULL;
2416                 }
2417                 return(xmlGetNoNsProp(reader->node, name));
2418         }
2419
2420     /*
2421      * Namespace default decl
2422      */
2423     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2424                 ns = reader->node->nsDef;
2425                 while (ns != NULL) {
2426                         if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2427                                 ret = xmlStrdup(ns->href);
2428                                 break;
2429                         }
2430                         ns = ns->next;
2431                 }
2432     } else {
2433                 ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2434                 if (ns != NULL)
2435                         ret = xmlGetNsProp(reader->node, localname, ns->href);
2436         }
2437
2438     xmlFree(localname);
2439     if (prefix != NULL)
2440         xmlFree(prefix);
2441     return(ret);
2442 }
2443
2444
2445 /**
2446  * xmlTextReaderGetAttributeNs:
2447  * @reader:  the xmlTextReaderPtr used
2448  * @localName: the local name of the attribute.
2449  * @namespaceURI: the namespace URI of the attribute.
2450  *
2451  * Provides the value of the specified attribute
2452  *
2453  * Returns a string containing the value of the specified attribute, or NULL
2454  *    in case of error. The string must be deallocated by the caller.
2455  */
2456 xmlChar *
2457 xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
2458                             const xmlChar *namespaceURI) {
2459     xmlChar *prefix = NULL;
2460     xmlNsPtr ns;
2461
2462     if ((reader == NULL) || (localName == NULL))
2463         return(NULL);
2464     if (reader->node == NULL)
2465         return(NULL);
2466     if (reader->curnode != NULL)
2467         return(NULL);
2468
2469     /* TODO: handle the xmlDecl */
2470     if (reader->node->type != XML_ELEMENT_NODE)
2471         return(NULL);
2472
2473     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2474                 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2475                         prefix = BAD_CAST localName;
2476                 }
2477                 ns = reader->node->nsDef;
2478                 while (ns != NULL) {
2479                         if ((prefix == NULL && ns->prefix == NULL) ||
2480                                 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2481                                 return xmlStrdup(ns->href);
2482                         }
2483                         ns = ns->next;
2484                 }
2485                 return NULL;
2486     }
2487
2488     return(xmlGetNsProp(reader->node, localName, namespaceURI));
2489 }
2490
2491 /**
2492  * xmlTextReaderGetRemainder:
2493  * @reader:  the xmlTextReaderPtr used
2494  *
2495  * Method to get the remainder of the buffered XML. this method stops the
2496  * parser, set its state to End Of File and return the input stream with
2497  * what is left that the parser did not use.
2498  *
2499  * The implementation is not good, the parser certainly procgressed past
2500  * what's left in reader->input, and there is an allocation problem. Best
2501  * would be to rewrite it differently.
2502  *
2503  * Returns the xmlParserInputBufferPtr attached to the XML or NULL
2504  *    in case of error.
2505  */
2506 xmlParserInputBufferPtr
2507 xmlTextReaderGetRemainder(xmlTextReaderPtr reader) {
2508     xmlParserInputBufferPtr ret = NULL;
2509
2510     if (reader == NULL)
2511         return(NULL);
2512     if (reader->node == NULL)
2513         return(NULL);
2514
2515     reader->node = NULL;
2516     reader->curnode = NULL;
2517     reader->mode = XML_TEXTREADER_MODE_EOF;
2518     if (reader->ctxt != NULL) {
2519         xmlStopParser(reader->ctxt);
2520         if (reader->ctxt->myDoc != NULL) {
2521             if (reader->preserve == 0)
2522                 xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
2523             reader->ctxt->myDoc = NULL;
2524         }
2525     }
2526     if (reader->allocs & XML_TEXTREADER_INPUT) {
2527         ret = reader->input;
2528         reader->input = NULL;
2529         reader->allocs -= XML_TEXTREADER_INPUT;
2530     } else {
2531         /*
2532          * Hum, one may need to duplicate the data structure because
2533          * without reference counting the input may be freed twice:
2534          *   - by the layer which allocated it.
2535          *   - by the layer to which would have been returned to.
2536          */
2537         TODO
2538         return(NULL);
2539     }
2540     return(ret);
2541 }
2542
2543 /**
2544  * xmlTextReaderLookupNamespace:
2545  * @reader:  the xmlTextReaderPtr used
2546  * @prefix: the prefix whose namespace URI is to be resolved. To return
2547  *          the default namespace, specify NULL
2548  *
2549  * Resolves a namespace prefix in the scope of the current element.
2550  *
2551  * Returns a string containing the namespace URI to which the prefix maps
2552  *    or NULL in case of error. The string must be deallocated by the caller.
2553  */
2554 xmlChar *
2555 xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) {
2556     xmlNsPtr ns;
2557
2558     if (reader == NULL)
2559         return(NULL);
2560     if (reader->node == NULL)
2561         return(NULL);
2562
2563     ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
2564     if (ns == NULL)
2565         return(NULL);
2566     return(xmlStrdup(ns->href));
2567 }
2568
2569 /**
2570  * xmlTextReaderMoveToAttributeNo:
2571  * @reader:  the xmlTextReaderPtr used
2572  * @no: the zero-based index of the attribute relative to the containing
2573  *      element.
2574  *
2575  * Moves the position of the current instance to the attribute with
2576  * the specified index relative to the containing element.
2577  *
2578  * Returns 1 in case of success, -1 in case of error, 0 if not found
2579  */
2580 int
2581 xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) {
2582     int i;
2583     xmlAttrPtr cur;
2584     xmlNsPtr ns;
2585
2586     if (reader == NULL)
2587         return(-1);
2588     if (reader->node == NULL)
2589         return(-1);
2590     /* TODO: handle the xmlDecl */
2591     if (reader->node->type != XML_ELEMENT_NODE)
2592         return(-1);
2593
2594     reader->curnode = NULL;
2595
2596     ns = reader->node->nsDef;
2597     for (i = 0;(i < no) && (ns != NULL);i++) {
2598         ns = ns->next;
2599     }
2600     if (ns != NULL) {
2601         reader->curnode = (xmlNodePtr) ns;
2602         return(1);
2603     }
2604
2605     cur = reader->node->properties;
2606     if (cur == NULL)
2607         return(0);
2608     for (;i < no;i++) {
2609         cur = cur->next;
2610         if (cur == NULL)
2611             return(0);
2612     }
2613     /* TODO walk the DTD if present */
2614
2615     reader->curnode = (xmlNodePtr) cur;
2616     return(1);
2617 }
2618
2619 /**
2620  * xmlTextReaderMoveToAttribute:
2621  * @reader:  the xmlTextReaderPtr used
2622  * @name: the qualified name of the attribute.
2623  *
2624  * Moves the position of the current instance to the attribute with
2625  * the specified qualified name.
2626  *
2627  * Returns 1 in case of success, -1 in case of error, 0 if not found
2628  */
2629 int
2630 xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
2631     xmlChar *prefix = NULL;
2632     xmlChar *localname;
2633     xmlNsPtr ns;
2634     xmlAttrPtr prop;
2635
2636     if ((reader == NULL) || (name == NULL))
2637         return(-1);
2638     if (reader->node == NULL)
2639         return(-1);
2640
2641     /* TODO: handle the xmlDecl */
2642     if (reader->node->type != XML_ELEMENT_NODE)
2643         return(0);
2644
2645     localname = xmlSplitQName2(name, &prefix);
2646     if (localname == NULL) {
2647         /*
2648          * Namespace default decl
2649          */
2650         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2651             ns = reader->node->nsDef;
2652             while (ns != NULL) {
2653                 if (ns->prefix == NULL) {
2654                     reader->curnode = (xmlNodePtr) ns;
2655                     return(1);
2656                 }
2657                 ns = ns->next;
2658             }
2659             return(0);
2660         }
2661
2662         prop = reader->node->properties;
2663         while (prop != NULL) {
2664             /*
2665              * One need to have
2666              *   - same attribute names
2667              *   - and the attribute carrying that namespace
2668              */
2669             if ((xmlStrEqual(prop->name, name)) &&
2670                 ((prop->ns == NULL) || (prop->ns->prefix == NULL))) {
2671                 reader->curnode = (xmlNodePtr) prop;
2672                 return(1);
2673             }
2674             prop = prop->next;
2675         }
2676         return(0);
2677     }
2678
2679     /*
2680      * Namespace default decl
2681      */
2682     if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
2683         ns = reader->node->nsDef;
2684         while (ns != NULL) {
2685             if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) {
2686                 reader->curnode = (xmlNodePtr) ns;
2687                 goto found;
2688             }
2689             ns = ns->next;
2690         }
2691         goto not_found;
2692     }
2693     prop = reader->node->properties;
2694     while (prop != NULL) {
2695         /*
2696          * One need to have
2697          *   - same attribute names
2698          *   - and the attribute carrying that namespace
2699          */
2700         if ((xmlStrEqual(prop->name, localname)) &&
2701             (prop->ns != NULL) && (xmlStrEqual(prop->ns->prefix, prefix))) {
2702             reader->curnode = (xmlNodePtr) prop;
2703             goto found;
2704         }
2705         prop = prop->next;
2706     }
2707 not_found:
2708     if (localname != NULL)
2709         xmlFree(localname);
2710     if (prefix != NULL)
2711         xmlFree(prefix);
2712     return(0);
2713
2714 found:
2715     if (localname != NULL)
2716         xmlFree(localname);
2717     if (prefix != NULL)
2718         xmlFree(prefix);
2719     return(1);
2720 }
2721
2722 /**
2723  * xmlTextReaderMoveToAttributeNs:
2724  * @reader:  the xmlTextReaderPtr used
2725  * @localName:  the local name of the attribute.
2726  * @namespaceURI:  the namespace URI of the attribute.
2727  *
2728  * Moves the position of the current instance to the attribute with the
2729  * specified local name and namespace URI.
2730  *
2731  * Returns 1 in case of success, -1 in case of error, 0 if not found
2732  */
2733 int
2734 xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader,
2735         const xmlChar *localName, const xmlChar *namespaceURI) {
2736     xmlAttrPtr prop;
2737     xmlNodePtr node;
2738     xmlNsPtr ns;
2739     xmlChar *prefix = NULL;
2740
2741     if ((reader == NULL) || (localName == NULL) || (namespaceURI == NULL))
2742         return(-1);
2743     if (reader->node == NULL)
2744         return(-1);
2745     if (reader->node->type != XML_ELEMENT_NODE)
2746         return(0);
2747     node = reader->node;
2748
2749     if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
2750                 if (! xmlStrEqual(localName, BAD_CAST "xmlns")) {
2751                         prefix = BAD_CAST localName;
2752                 }
2753                 ns = reader->node->nsDef;
2754                 while (ns != NULL) {
2755                         if ((prefix == NULL && ns->prefix == NULL) ||
2756                                 ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) {
2757                                 reader->curnode = (xmlNodePtr) ns;
2758                                 return(1);
2759                         }
2760                         ns = ns->next;
2761                 }
2762                 return(0);
2763     }
2764
2765     prop = node->properties;
2766     while (prop != NULL) {
2767         /*
2768          * One need to have
2769          *   - same attribute names
2770          *   - and the attribute carrying that namespace
2771          */
2772         if (xmlStrEqual(prop->name, localName) &&
2773             ((prop->ns != NULL) &&
2774              (xmlStrEqual(prop->ns->href, namespaceURI)))) {
2775             reader->curnode = (xmlNodePtr) prop;
2776             return(1);
2777         }
2778         prop = prop->next;
2779     }
2780     return(0);
2781 }
2782
2783 /**
2784  * xmlTextReaderMoveToFirstAttribute:
2785  * @reader:  the xmlTextReaderPtr used
2786  *
2787  * Moves the position of the current instance to the first attribute
2788  * associated with the current node.
2789  *
2790  * Returns 1 in case of success, -1 in case of error, 0 if not found
2791  */
2792 int
2793 xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader) {
2794     if (reader == NULL)
2795         return(-1);
2796     if (reader->node == NULL)
2797         return(-1);
2798     if (reader->node->type != XML_ELEMENT_NODE)
2799         return(0);
2800
2801     if (reader->node->nsDef != NULL) {
2802         reader->curnode = (xmlNodePtr) reader->node->nsDef;
2803         return(1);
2804     }
2805     if (reader->node->properties != NULL) {
2806         reader->curnode = (xmlNodePtr) reader->node->properties;
2807         return(1);
2808     }
2809     return(0);
2810 }
2811
2812 /**
2813  * xmlTextReaderMoveToNextAttribute:
2814  * @reader:  the xmlTextReaderPtr used
2815  *
2816  * Moves the position of the current instance to the next attribute
2817  * associated with the current node.
2818  *
2819  * Returns 1 in case of success, -1 in case of error, 0 if not found
2820  */
2821 int
2822 xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader) {
2823     if (reader == NULL)
2824         return(-1);
2825     if (reader->node == NULL)
2826         return(-1);
2827     if (reader->node->type != XML_ELEMENT_NODE)
2828         return(0);
2829     if (reader->curnode == NULL)
2830         return(xmlTextReaderMoveToFirstAttribute(reader));
2831
2832     if (reader->curnode->type == XML_NAMESPACE_DECL) {
2833         xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2834         if (ns->next != NULL) {
2835             reader->curnode = (xmlNodePtr) ns->next;
2836             return(1);
2837         }
2838         if (reader->node->properties != NULL) {
2839             reader->curnode = (xmlNodePtr) reader->node->properties;
2840             return(1);
2841         }
2842         return(0);
2843     } else if ((reader->curnode->type == XML_ATTRIBUTE_NODE) &&
2844                (reader->curnode->next != NULL)) {
2845         reader->curnode = reader->curnode->next;
2846         return(1);
2847     }
2848     return(0);
2849 }
2850
2851 /**
2852  * xmlTextReaderMoveToElement:
2853  * @reader:  the xmlTextReaderPtr used
2854  *
2855  * Moves the position of the current instance to the node that
2856  * contains the current Attribute  node.
2857  *
2858  * Returns 1 in case of success, -1 in case of error, 0 if not moved
2859  */
2860 int
2861 xmlTextReaderMoveToElement(xmlTextReaderPtr reader) {
2862     if (reader == NULL)
2863         return(-1);
2864     if (reader->node == NULL)
2865         return(-1);
2866     if (reader->node->type != XML_ELEMENT_NODE)
2867         return(0);
2868     if (reader->curnode != NULL) {
2869         reader->curnode = NULL;
2870         return(1);
2871     }
2872     return(0);
2873 }
2874
2875 /**
2876  * xmlTextReaderReadAttributeValue:
2877  * @reader:  the xmlTextReaderPtr used
2878  *
2879  * Parses an attribute value into one or more Text and EntityReference nodes.
2880  *
2881  * Returns 1 in case of success, 0 if the reader was not positionned on an
2882  *         ttribute node or all the attribute values have been read, or -1
2883  *         in case of error.
2884  */
2885 int
2886 xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
2887     if (reader == NULL)
2888         return(-1);
2889     if (reader->node == NULL)
2890         return(-1);
2891     if (reader->curnode == NULL)
2892         return(0);
2893     if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
2894         if (reader->curnode->children == NULL)
2895             return(0);
2896         reader->curnode = reader->curnode->children;
2897     } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
2898         xmlNsPtr ns = (xmlNsPtr) reader->curnode;
2899
2900         if (reader->faketext == NULL) {
2901             reader->faketext = xmlNewDocText(reader->node->doc,
2902                                              ns->href);
2903         } else {
2904             if ((reader->faketext->content != NULL) &&
2905                 (reader->faketext->content !=
2906                  (xmlChar *) &(reader->faketext->properties)))
2907                 xmlFree(reader->faketext->content);
2908             reader->faketext->content = xmlStrdup(ns->href);
2909         }
2910         reader->curnode = reader->faketext;
2911     } else {
2912         if (reader->curnode->next == NULL)
2913             return(0);
2914         reader->curnode = reader->curnode->next;
2915     }
2916     return(1);
2917 }
2918
2919 /**
2920  * xmlTextReaderConstEncoding:
2921  * @reader:  the xmlTextReaderPtr used
2922  *
2923  * Determine the encoding of the document being read.
2924  *
2925  * Returns a string containing the encoding of the document or NULL in
2926  * case of error.  The string is deallocated with the reader.
2927  */
2928 const xmlChar *
2929 xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
2930     xmlDocPtr doc = NULL;
2931     if (reader == NULL)
2932         return(NULL);
2933     if (reader->doc != NULL)
2934         doc = reader->doc;
2935     else if (reader->ctxt != NULL)
2936         doc = reader->ctxt->myDoc;
2937     if (doc == NULL)
2938         return(NULL);
2939
2940     if (doc->encoding == NULL)
2941         return(NULL);
2942     else
2943       return(CONSTSTR(doc->encoding));
2944 }
2945
2946
2947 /************************************************************************
2948  *                                                                      *
2949  *                      Acces API to the current node                   *
2950  *                                                                      *
2951  ************************************************************************/
2952 /**
2953  * xmlTextReaderAttributeCount:
2954  * @reader:  the xmlTextReaderPtr used
2955  *
2956  * Provides the number of attributes of the current node
2957  *
2958  * Returns 0 i no attributes, -1 in case of error or the attribute count
2959  */
2960 int
2961 xmlTextReaderAttributeCount(xmlTextReaderPtr reader) {
2962     int ret;
2963     xmlAttrPtr attr;
2964     xmlNsPtr ns;
2965     xmlNodePtr node;
2966
2967     if (reader == NULL)
2968         return(-1);
2969     if (reader->node == NULL)
2970         return(0);
2971
2972     if (reader->curnode != NULL)
2973         node = reader->curnode;
2974     else
2975         node = reader->node;
2976
2977     if (node->type != XML_ELEMENT_NODE)
2978         return(0);
2979     if ((reader->state == XML_TEXTREADER_END) ||
2980         (reader->state == XML_TEXTREADER_BACKTRACK))
2981         return(0);
2982     ret = 0;
2983     attr = node->properties;
2984     while (attr != NULL) {
2985         ret++;
2986         attr = attr->next;
2987     }
2988     ns = node->nsDef;
2989     while (ns != NULL) {
2990         ret++;
2991         ns = ns->next;
2992     }
2993     return(ret);
2994 }
2995
2996 /**
2997  * xmlTextReaderNodeType:
2998  * @reader:  the xmlTextReaderPtr used
2999  *
3000  * Get the node type of the current node
3001  * Reference:
3002  * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html
3003  *
3004  * Returns the xmlNodeType of the current node or -1 in case of error
3005  */
3006 int
3007 xmlTextReaderNodeType(xmlTextReaderPtr reader) {
3008     xmlNodePtr node;
3009
3010     if (reader == NULL)
3011         return(-1);
3012     if (reader->node == NULL)
3013         return(XML_READER_TYPE_NONE);
3014     if (reader->curnode != NULL)
3015         node = reader->curnode;
3016     else
3017         node = reader->node;
3018     switch (node->type) {
3019         case XML_ELEMENT_NODE:
3020             if ((reader->state == XML_TEXTREADER_END) ||
3021                 (reader->state == XML_TEXTREADER_BACKTRACK))
3022                 return(XML_READER_TYPE_END_ELEMENT);
3023             return(XML_READER_TYPE_ELEMENT);
3024         case XML_NAMESPACE_DECL:
3025         case XML_ATTRIBUTE_NODE:
3026             return(XML_READER_TYPE_ATTRIBUTE);
3027         case XML_TEXT_NODE:
3028             if (xmlIsBlankNode(reader->node)) {
3029                 if (xmlNodeGetSpacePreserve(reader->node))
3030                     return(XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
3031                 else
3032                     return(XML_READER_TYPE_WHITESPACE);
3033             } else {
3034                 return(XML_READER_TYPE_TEXT);
3035             }
3036         case XML_CDATA_SECTION_NODE:
3037             return(XML_READER_TYPE_CDATA);
3038         case XML_ENTITY_REF_NODE:
3039             return(XML_READER_TYPE_ENTITY_REFERENCE);
3040         case XML_ENTITY_NODE:
3041             return(XML_READER_TYPE_ENTITY);
3042         case XML_PI_NODE:
3043             return(XML_READER_TYPE_PROCESSING_INSTRUCTION);
3044         case XML_COMMENT_NODE:
3045             return(XML_READER_TYPE_COMMENT);
3046         case XML_DOCUMENT_NODE:
3047         case XML_HTML_DOCUMENT_NODE:
3048 #ifdef LIBXML_DOCB_ENABLED
3049         case XML_DOCB_DOCUMENT_NODE:
3050 #endif
3051             return(XML_READER_TYPE_DOCUMENT);
3052         case XML_DOCUMENT_FRAG_NODE:
3053             return(XML_READER_TYPE_DOCUMENT_FRAGMENT);
3054         case XML_NOTATION_NODE:
3055             return(XML_READER_TYPE_NOTATION);
3056         case XML_DOCUMENT_TYPE_NODE:
3057         case XML_DTD_NODE:
3058             return(XML_READER_TYPE_DOCUMENT_TYPE);
3059
3060         case XML_ELEMENT_DECL:
3061         case XML_ATTRIBUTE_DECL:
3062         case XML_ENTITY_DECL:
3063         case XML_XINCLUDE_START:
3064         case XML_XINCLUDE_END:
3065             return(XML_READER_TYPE_NONE);
3066     }
3067     return(-1);
3068 }
3069
3070 /**
3071  * xmlTextReaderIsEmptyElement:
3072  * @reader:  the xmlTextReaderPtr used
3073  *
3074  * Check if the current node is empty
3075  *
3076  * Returns 1 if empty, 0 if not and -1 in case of error
3077  */
3078 int
3079 xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
3080     if ((reader == NULL) || (reader->node == NULL))
3081         return(-1);
3082     if (reader->node->type != XML_ELEMENT_NODE)
3083         return(0);
3084     if (reader->curnode != NULL)
3085         return(0);
3086     if (reader->node->children != NULL)
3087         return(0);
3088     if (reader->state == XML_TEXTREADER_END)
3089         return(0);
3090     if (reader->doc != NULL)
3091         return(1);
3092 #ifdef LIBXML_XINCLUDE_ENABLED
3093     if (reader->in_xinclude > 0)
3094         return(1);
3095 #endif
3096     return((reader->node->extra & NODE_IS_EMPTY) != 0);
3097 }
3098
3099 /**
3100  * xmlTextReaderLocalName:
3101  * @reader:  the xmlTextReaderPtr used
3102  *
3103  * The local name of the node.
3104  *
3105  * Returns the local name or NULL if not available,
3106  *   if non NULL it need to be freed by the caller.
3107  */
3108 xmlChar *
3109 xmlTextReaderLocalName(xmlTextReaderPtr reader) {
3110     xmlNodePtr node;
3111     if ((reader == NULL) || (reader->node == NULL))
3112         return(NULL);
3113     if (reader->curnode != NULL)
3114         node = reader->curnode;
3115     else
3116         node = reader->node;
3117     if (node->type == XML_NAMESPACE_DECL) {
3118         xmlNsPtr ns = (xmlNsPtr) node;
3119         if (ns->prefix == NULL)
3120             return(xmlStrdup(BAD_CAST "xmlns"));
3121         else
3122             return(xmlStrdup(ns->prefix));
3123     }
3124     if ((node->type != XML_ELEMENT_NODE) &&
3125         (node->type != XML_ATTRIBUTE_NODE))
3126         return(xmlTextReaderName(reader));
3127     return(xmlStrdup(node->name));
3128 }
3129
3130 /**
3131  * xmlTextReaderConstLocalName:
3132  * @reader:  the xmlTextReaderPtr used
3133  *
3134  * The local name of the node.
3135  *
3136  * Returns the local name or NULL if not available, the
3137  *         string will be deallocated with the reader.
3138  */
3139 const xmlChar *
3140 xmlTextReaderConstLocalName(xmlTextReaderPtr reader) {
3141     xmlNodePtr node;
3142     if ((reader == NULL) || (reader->node == NULL))
3143         return(NULL);
3144     if (reader->curnode != NULL)
3145         node = reader->curnode;
3146     else
3147         node = reader->node;
3148     if (node->type == XML_NAMESPACE_DECL) {
3149         xmlNsPtr ns = (xmlNsPtr) node;
3150         if (ns->prefix == NULL)
3151             return(CONSTSTR(BAD_CAST "xmlns"));
3152         else
3153             return(ns->prefix);
3154     }
3155     if ((node->type != XML_ELEMENT_NODE) &&
3156         (node->type != XML_ATTRIBUTE_NODE))
3157         return(xmlTextReaderConstName(reader));
3158     return(node->name);
3159 }
3160
3161 /**
3162  * xmlTextReaderName:
3163  * @reader:  the xmlTextReaderPtr used
3164  *
3165  * The qualified name of the node, equal to Prefix :LocalName.
3166  *
3167  * Returns the local name or NULL if not available,
3168  *   if non NULL it need to be freed by the caller.
3169  */
3170 xmlChar *
3171 xmlTextReaderName(xmlTextReaderPtr reader) {
3172     xmlNodePtr node;
3173     xmlChar *ret;
3174
3175     if ((reader == NULL) || (reader->node == NULL))
3176         return(NULL);
3177     if (reader->curnode != NULL)
3178         node = reader->curnode;
3179     else
3180         node = reader->node;
3181     switch (node->type) {
3182         case XML_ELEMENT_NODE:
3183         case XML_ATTRIBUTE_NODE:
3184             if ((node->ns == NULL) ||
3185                 (node->ns->prefix == NULL))
3186                 return(xmlStrdup(node->name));
3187
3188             ret = xmlStrdup(node->ns->prefix);
3189             ret = xmlStrcat(ret, BAD_CAST ":");
3190             ret = xmlStrcat(ret, node->name);
3191             return(ret);
3192         case XML_TEXT_NODE:
3193             return(xmlStrdup(BAD_CAST "#text"));
3194         case XML_CDATA_SECTION_NODE:
3195             return(xmlStrdup(BAD_CAST "#cdata-section"));
3196         case XML_ENTITY_NODE:
3197         case XML_ENTITY_REF_NODE:
3198             return(xmlStrdup(node->name));
3199         case XML_PI_NODE:
3200             return(xmlStrdup(node->name));
3201         case XML_COMMENT_NODE:
3202             return(xmlStrdup(BAD_CAST "#comment"));
3203         case XML_DOCUMENT_NODE:
3204         case XML_HTML_DOCUMENT_NODE:
3205 #ifdef LIBXML_DOCB_ENABLED
3206         case XML_DOCB_DOCUMENT_NODE:
3207 #endif
3208             return(xmlStrdup(BAD_CAST "#document"));
3209         case XML_DOCUMENT_FRAG_NODE:
3210             return(xmlStrdup(BAD_CAST "#document-fragment"));
3211         case XML_NOTATION_NODE:
3212             return(xmlStrdup(node->name));
3213         case XML_DOCUMENT_TYPE_NODE:
3214         case XML_DTD_NODE:
3215             return(xmlStrdup(node->name));
3216         case XML_NAMESPACE_DECL: {
3217             xmlNsPtr ns = (xmlNsPtr) node;
3218
3219             ret = xmlStrdup(BAD_CAST "xmlns");
3220             if (ns->prefix == NULL)
3221                 return(ret);
3222             ret = xmlStrcat(ret, BAD_CAST ":");
3223             ret = xmlStrcat(ret, ns->prefix);
3224             return(ret);
3225         }
3226
3227         case XML_ELEMENT_DECL:
3228         case XML_ATTRIBUTE_DECL:
3229         case XML_ENTITY_DECL:
3230         case XML_XINCLUDE_START:
3231         case XML_XINCLUDE_END:
3232             return(NULL);
3233     }
3234     return(NULL);
3235 }
3236
3237 /**
3238  * xmlTextReaderConstName:
3239  * @reader:  the xmlTextReaderPtr used
3240  *
3241  * The qualified name of the node, equal to Prefix :LocalName.
3242  *
3243  * Returns the local name or NULL if not available, the string is
3244  *         deallocated with the reader.
3245  */
3246 const xmlChar *
3247 xmlTextReaderConstName(xmlTextReaderPtr reader) {
3248     xmlNodePtr node;
3249
3250     if ((reader == NULL) || (reader->node == NULL))
3251         return(NULL);
3252     if (reader->curnode != NULL)
3253         node = reader->curnode;
3254     else
3255         node = reader->node;
3256     switch (node->type) {
3257         case XML_ELEMENT_NODE:
3258         case XML_ATTRIBUTE_NODE:
3259             if ((node->ns == NULL) ||
3260                 (node->ns->prefix == NULL))
3261                 return(node->name);
3262             return(CONSTQSTR(node->ns->prefix, node->name));
3263         case XML_TEXT_NODE:
3264             return(CONSTSTR(BAD_CAST "#text"));
3265         case XML_CDATA_SECTION_NODE:
3266             return(CONSTSTR(BAD_CAST "#cdata-section"));
3267         case XML_ENTITY_NODE:
3268         case XML_ENTITY_REF_NODE:
3269             return(CONSTSTR(node->name));
3270         case XML_PI_NODE:
3271             return(CONSTSTR(node->name));
3272         case XML_COMMENT_NODE:
3273             return(CONSTSTR(BAD_CAST "#comment"));
3274         case XML_DOCUMENT_NODE:
3275         case XML_HTML_DOCUMENT_NODE:
3276 #ifdef LIBXML_DOCB_ENABLED
3277         case XML_DOCB_DOCUMENT_NODE:
3278 #endif
3279             return(CONSTSTR(BAD_CAST "#document"));
3280         case XML_DOCUMENT_FRAG_NODE:
3281             return(CONSTSTR(BAD_CAST "#document-fragment"));
3282         case XML_NOTATION_NODE:
3283             return(CONSTSTR(node->name));
3284         case XML_DOCUMENT_TYPE_NODE:
3285         case XML_DTD_NODE:
3286             return(CONSTSTR(node->name));
3287         case XML_NAMESPACE_DECL: {
3288             xmlNsPtr ns = (xmlNsPtr) node;
3289
3290             if (ns->prefix == NULL)
3291                 return(CONSTSTR(BAD_CAST "xmlns"));
3292             return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix));
3293         }
3294
3295         case XML_ELEMENT_DECL:
3296         case XML_ATTRIBUTE_DECL:
3297         case XML_ENTITY_DECL:
3298         case XML_XINCLUDE_START:
3299         case XML_XINCLUDE_END:
3300             return(NULL);
3301     }
3302     return(NULL);
3303 }
3304
3305 /**
3306  * xmlTextReaderPrefix:
3307  * @reader:  the xmlTextReaderPtr used
3308  *
3309  * A shorthand reference to the namespace associated with the node.
3310  *
3311  * Returns the prefix or NULL if not available,
3312  *    if non NULL it need to be freed by the caller.
3313  */
3314 xmlChar *
3315 xmlTextReaderPrefix(xmlTextReaderPtr reader) {
3316     xmlNodePtr node;
3317     if ((reader == NULL) || (reader->node == NULL))
3318         return(NULL);
3319     if (reader->curnode != NULL)
3320         node = reader->curnode;
3321     else
3322         node = reader->node;
3323     if (node->type == XML_NAMESPACE_DECL) {
3324         xmlNsPtr ns = (xmlNsPtr) node;
3325         if (ns->prefix == NULL)
3326             return(NULL);
3327         return(xmlStrdup(BAD_CAST "xmlns"));
3328     }
3329     if ((node->type != XML_ELEMENT_NODE) &&
3330         (node->type != XML_ATTRIBUTE_NODE))
3331         return(NULL);
3332     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3333         return(xmlStrdup(node->ns->prefix));
3334     return(NULL);
3335 }
3336
3337 /**
3338  * xmlTextReaderConstPrefix:
3339  * @reader:  the xmlTextReaderPtr used
3340  *
3341  * A shorthand reference to the namespace associated with the node.
3342  *
3343  * Returns the prefix or NULL if not available, the string is deallocated
3344  *         with the reader.
3345  */
3346 const xmlChar *
3347 xmlTextReaderConstPrefix(xmlTextReaderPtr reader) {
3348     xmlNodePtr node;
3349     if ((reader == NULL) || (reader->node == NULL))
3350         return(NULL);
3351     if (reader->curnode != NULL)
3352         node = reader->curnode;
3353     else
3354         node = reader->node;
3355     if (node->type == XML_NAMESPACE_DECL) {
3356         xmlNsPtr ns = (xmlNsPtr) node;
3357         if (ns->prefix == NULL)
3358             return(NULL);
3359         return(CONSTSTR(BAD_CAST "xmlns"));
3360     }
3361     if ((node->type != XML_ELEMENT_NODE) &&
3362         (node->type != XML_ATTRIBUTE_NODE))
3363         return(NULL);
3364     if ((node->ns != NULL) && (node->ns->prefix != NULL))
3365         return(CONSTSTR(node->ns->prefix));
3366     return(NULL);
3367 }
3368
3369 /**
3370  * xmlTextReaderNamespaceUri:
3371  * @reader:  the xmlTextReaderPtr used
3372  *
3373  * The URI defining the namespace associated with the node.
3374  *
3375  * Returns the namespace URI or NULL if not available,
3376  *    if non NULL it need to be freed by the caller.
3377  */
3378 xmlChar *
3379 xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) {
3380     xmlNodePtr node;
3381     if ((reader == NULL) || (reader->node == NULL))
3382         return(NULL);
3383     if (reader->curnode != NULL)
3384         node = reader->curnode;
3385     else
3386         node = reader->node;
3387     if (node->type == XML_NAMESPACE_DECL)
3388         return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3389     if ((node->type != XML_ELEMENT_NODE) &&
3390         (node->type != XML_ATTRIBUTE_NODE))
3391         return(NULL);
3392     if (node->ns != NULL)
3393         return(xmlStrdup(node->ns->href));
3394     return(NULL);
3395 }
3396
3397 /**
3398  * xmlTextReaderConstNamespaceUri:
3399  * @reader:  the xmlTextReaderPtr used
3400  *
3401  * The URI defining the namespace associated with the node.
3402  *
3403  * Returns the namespace URI or NULL if not available, the string
3404  *         will be deallocated with the reader
3405  */
3406 const xmlChar *
3407 xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) {
3408     xmlNodePtr node;
3409     if ((reader == NULL) || (reader->node == NULL))
3410         return(NULL);
3411     if (reader->curnode != NULL)
3412         node = reader->curnode;
3413     else
3414         node = reader->node;
3415     if (node->type == XML_NAMESPACE_DECL)
3416         return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/"));
3417     if ((node->type != XML_ELEMENT_NODE) &&
3418         (node->type != XML_ATTRIBUTE_NODE))
3419         return(NULL);
3420     if (node->ns != NULL)
3421         return(CONSTSTR(node->ns->href));
3422     return(NULL);
3423 }
3424
3425 /**
3426  * xmlTextReaderBaseUri:
3427  * @reader:  the xmlTextReaderPtr used
3428  *
3429  * The base URI of the node.
3430  *
3431  * Returns the base URI or NULL if not available,
3432  *    if non NULL it need to be freed by the caller.
3433  */
3434 xmlChar *
3435 xmlTextReaderBaseUri(xmlTextReaderPtr reader) {
3436     if ((reader == NULL) || (reader->node == NULL))
3437         return(NULL);
3438     return(xmlNodeGetBase(NULL, reader->node));
3439 }
3440
3441 /**
3442  * xmlTextReaderConstBaseUri:
3443  * @reader:  the xmlTextReaderPtr used
3444  *
3445  * The base URI of the node.
3446  *
3447  * Returns the base URI or NULL if not available, the string
3448  *         will be deallocated with the reader
3449  */
3450 const xmlChar *
3451 xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) {
3452     xmlChar *tmp;
3453     const xmlChar *ret;
3454
3455     if ((reader == NULL) || (reader->node == NULL))
3456         return(NULL);
3457     tmp = xmlNodeGetBase(NULL, reader->node);
3458     if (tmp == NULL)
3459         return(NULL);
3460     ret = CONSTSTR(tmp);
3461     xmlFree(tmp);
3462     return(ret);
3463 }
3464
3465 /**
3466  * xmlTextReaderDepth:
3467  * @reader:  the xmlTextReaderPtr used
3468  *
3469  * The depth of the node in the tree.
3470  *
3471  * Returns the depth or -1 in case of error
3472  */
3473 int
3474 xmlTextReaderDepth(xmlTextReaderPtr reader) {
3475     if (reader == NULL)
3476         return(-1);
3477     if (reader->node == NULL)
3478         return(0);
3479
3480     if (reader->curnode != NULL) {
3481         if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
3482             (reader->curnode->type == XML_NAMESPACE_DECL))
3483             return(reader->depth + 1);
3484         return(reader->depth + 2);
3485     }
3486     return(reader->depth);
3487 }
3488
3489 /**
3490  * xmlTextReaderHasAttributes:
3491  * @reader:  the xmlTextReaderPtr used
3492  *
3493  * Whether the node has attributes.
3494  *
3495  * Returns 1 if true, 0 if false, and -1 in case or error
3496  */
3497 int
3498 xmlTextReaderHasAttributes(xmlTextReaderPtr reader) {
3499     xmlNodePtr node;
3500     if (reader == NULL)
3501         return(-1);
3502     if (reader->node == NULL)
3503         return(0);
3504     if (reader->curnode != NULL)
3505         node = reader->curnode;
3506     else
3507         node = reader->node;
3508
3509     if ((node->type == XML_ELEMENT_NODE) &&
3510         ((node->properties != NULL) || (node->nsDef != NULL)))
3511         return(1);
3512     /* TODO: handle the xmlDecl */
3513     return(0);
3514 }
3515
3516 /**
3517  * xmlTextReaderHasValue:
3518  * @reader:  the xmlTextReaderPtr used
3519  *
3520  * Whether the node can have a text value.
3521  *
3522  * Returns 1 if true, 0 if false, and -1 in case or error
3523  */
3524 int
3525 xmlTextReaderHasValue(xmlTextReaderPtr reader) {
3526     xmlNodePtr node;
3527     if (reader == NULL)
3528         return(-1);
3529     if (reader->node == NULL)
3530         return(0);
3531     if (reader->curnode != NULL)
3532         node = reader->curnode;
3533     else
3534         node = reader->node;
3535
3536     switch (node->type) {
3537         case XML_ATTRIBUTE_NODE:
3538         case XML_TEXT_NODE:
3539         case XML_CDATA_SECTION_NODE:
3540         case XML_PI_NODE:
3541         case XML_COMMENT_NODE:
3542         case XML_NAMESPACE_DECL:
3543             return(1);
3544         default:
3545             break;
3546     }
3547     return(0);
3548 }
3549
3550 /**
3551  * xmlTextReaderValue:
3552  * @reader:  the xmlTextReaderPtr used
3553  *
3554  * Provides the text value of the node if present
3555  *
3556  * Returns the string or NULL if not available. The result must be deallocated
3557  *     with xmlFree()
3558  */
3559 xmlChar *
3560 xmlTextReaderValue(xmlTextReaderPtr reader) {
3561     xmlNodePtr node;
3562     if (reader == NULL)
3563         return(NULL);
3564     if (reader->node == NULL)
3565         return(NULL);
3566     if (reader->curnode != NULL)
3567         node = reader->curnode;
3568     else
3569         node = reader->node;
3570
3571     switch (node->type) {
3572         case XML_NAMESPACE_DECL:
3573             return(xmlStrdup(((xmlNsPtr) node)->href));
3574         case XML_ATTRIBUTE_NODE:{
3575             xmlAttrPtr attr = (xmlAttrPtr) node;
3576
3577             if (attr->parent != NULL)
3578                 return (xmlNodeListGetString
3579                         (attr->parent->doc, attr->children, 1));
3580             else
3581                 return (xmlNodeListGetString(NULL, attr->children, 1));
3582             break;
3583         }
3584         case XML_TEXT_NODE:
3585         case XML_CDATA_SECTION_NODE:
3586         case XML_PI_NODE:
3587         case XML_COMMENT_NODE:
3588             if (node->content != NULL)
3589                 return (xmlStrdup(node->content));
3590         default:
3591             break;
3592     }
3593     return(NULL);
3594 }
3595
3596 /**
3597  * xmlTextReaderConstValue:
3598  * @reader:  the xmlTextReaderPtr used
3599  *
3600  * Provides the text value of the node if present
3601  *
3602  * Returns the string or NULL if not available. The result will be
3603  *     deallocated on the next Read() operation.
3604  */
3605 const xmlChar *
3606 xmlTextReaderConstValue(xmlTextReaderPtr reader) {
3607     xmlNodePtr node;
3608     if (reader == NULL)
3609         return(NULL);
3610     if (reader->node == NULL)
3611         return(NULL);
3612     if (reader->curnode != NULL)
3613         node = reader->curnode;
3614     else
3615         node = reader->node;
3616
3617     switch (node->type) {
3618         case XML_NAMESPACE_DECL:
3619             return(((xmlNsPtr) node)->href);
3620         case XML_ATTRIBUTE_NODE:{
3621             xmlAttrPtr attr = (xmlAttrPtr) node;
3622             const xmlChar *ret;
3623
3624             if ((attr->children != NULL) &&
3625                 (attr->children->type == XML_TEXT_NODE) &&
3626                 (attr->children->next == NULL))
3627                 return(attr->children->content);
3628             else {
3629                 if (reader->buffer == NULL) {
3630                     reader->buffer = xmlBufCreateSize(100);
3631                     if (reader->buffer == NULL) {
3632                         xmlGenericError(xmlGenericErrorContext,
3633                                         "xmlTextReaderSetup : malloc failed\n");
3634                         return (NULL);
3635                     }
3636                     xmlBufSetAllocationScheme(reader->buffer,
3637                                               XML_BUFFER_ALLOC_BOUNDED);
3638                 } else
3639                     xmlBufEmpty(reader->buffer);
3640                 xmlBufGetNodeContent(reader->buffer, node);
3641                 ret = xmlBufContent(reader->buffer);
3642                 if (ret == NULL) {
3643                     /* error on the buffer best to reallocate */
3644                     xmlBufFree(reader->buffer);
3645                     reader->buffer = xmlBufCreateSize(100);
3646                     xmlBufSetAllocationScheme(reader->buffer,
3647                                               XML_BUFFER_ALLOC_BOUNDED);
3648                     ret = BAD_CAST "";
3649                 }
3650                 return(ret);
3651             }
3652             break;
3653         }
3654         case XML_TEXT_NODE:
3655         case XML_CDATA_SECTION_NODE:
3656         case XML_PI_NODE:
3657         case XML_COMMENT_NODE:
3658             return(node->content);
3659         default:
3660             break;
3661     }
3662     return(NULL);
3663 }
3664
3665 /**
3666  * xmlTextReaderIsDefault:
3667  * @reader:  the xmlTextReaderPtr used
3668  *
3669  * Whether an Attribute  node was generated from the default value
3670  * defined in the DTD or schema.
3671  *
3672  * Returns 0 if not defaulted, 1 if defaulted, and -1 in case of error
3673  */
3674 int
3675 xmlTextReaderIsDefault(xmlTextReaderPtr reader) {
3676     if (reader == NULL)
3677         return(-1);
3678     return(0);
3679 }
3680
3681 /**
3682  * xmlTextReaderQuoteChar:
3683  * @reader:  the xmlTextReaderPtr used
3684  *
3685  * The quotation mark character used to enclose the value of an attribute.
3686  *
3687  * Returns " or ' and -1 in case of error
3688  */
3689 int
3690 xmlTextReaderQuoteChar(xmlTextReaderPtr reader) {
3691     if (reader == NULL)
3692         return(-1);
3693     /* TODO maybe lookup the attribute value for " first */
3694     return((int) '"');
3695 }
3696
3697 /**
3698  * xmlTextReaderXmlLang:
3699  * @reader:  the xmlTextReaderPtr used
3700  *
3701  * The xml:lang scope within which the node resides.
3702  *
3703  * Returns the xml:lang value or NULL if none exists.,
3704  *    if non NULL it need to be freed by the caller.
3705  */
3706 xmlChar *
3707 xmlTextReaderXmlLang(xmlTextReaderPtr reader) {
3708     if (reader == NULL)
3709         return(NULL);
3710     if (reader->node == NULL)
3711         return(NULL);
3712     return(xmlNodeGetLang(reader->node));
3713 }
3714
3715 /**
3716  * xmlTextReaderConstXmlLang:
3717  * @reader:  the xmlTextReaderPtr used
3718  *
3719  * The xml:lang scope within which the node resides.
3720  *
3721  * Returns the xml:lang value or NULL if none exists.
3722  */
3723 const xmlChar *
3724 xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) {
3725     xmlChar *tmp;
3726     const xmlChar *ret;
3727
3728     if (reader == NULL)
3729         return(NULL);
3730     if (reader->node == NULL)
3731         return(NULL);
3732     tmp = xmlNodeGetLang(reader->node);
3733     if (tmp == NULL)
3734         return(NULL);
3735     ret = CONSTSTR(tmp);
3736     xmlFree(tmp);
3737     return(ret);
3738 }
3739
3740 /**
3741  * xmlTextReaderConstString:
3742  * @reader:  the xmlTextReaderPtr used
3743  * @str:  the string to intern.
3744  *
3745  * Get an interned string from the reader, allows for example to
3746  * speedup string name comparisons
3747  *
3748  * Returns an interned copy of the string or NULL in case of error. The
3749  *         string will be deallocated with the reader.
3750  */
3751 const xmlChar *
3752 xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
3753     if (reader == NULL)
3754         return(NULL);
3755     return(CONSTSTR(str));
3756 }
3757
3758 /**
3759  * xmlTextReaderNormalization:
3760  * @reader:  the xmlTextReaderPtr used
3761  *
3762  * The value indicating whether to normalize white space and attribute values.
3763  * Since attribute value and end of line normalizations are a MUST in the XML
3764  * specification only the value true is accepted. The broken bahaviour of
3765  * accepting out of range character entities like &#0; is of course not
3766  * supported either.
3767  *
3768  * Returns 1 or -1 in case of error.
3769  */
3770 int
3771 xmlTextReaderNormalization(xmlTextReaderPtr reader) {
3772     if (reader == NULL)
3773         return(-1);
3774     return(1);
3775 }
3776
3777 /************************************************************************
3778  *                                                                      *
3779  *                      Extensions to the base APIs                     *
3780  *                                                                      *
3781  ************************************************************************/
3782
3783 /**
3784  * xmlTextReaderSetParserProp:
3785  * @reader:  the xmlTextReaderPtr used
3786  * @prop:  the xmlParserProperties to set
3787  * @value:  usually 0 or 1 to (de)activate it
3788  *
3789  * Change the parser processing behaviour by changing some of its internal
3790  * properties. Note that some properties can only be changed before any
3791  * read has been done.
3792  *
3793  * Returns 0 if the call was successful, or -1 in case of error
3794  */
3795 int
3796 xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
3797     xmlParserProperties p = (xmlParserProperties) prop;
3798     xmlParserCtxtPtr ctxt;
3799
3800     if ((reader == NULL) || (reader->ctxt == NULL))
3801         return(-1);
3802     ctxt = reader->ctxt;
3803
3804     switch (p) {
3805         case XML_PARSER_LOADDTD:
3806             if (value != 0) {
3807                 if (ctxt->loadsubset == 0) {
3808                     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
3809                         return(-1);
3810                     ctxt->loadsubset = XML_DETECT_IDS;
3811                 }
3812             } else {
3813                 ctxt->loadsubset = 0;
3814             }
3815             return(0);
3816         case XML_PARSER_DEFAULTATTRS:
3817             if (value != 0) {
3818                 ctxt->loadsubset |= XML_COMPLETE_ATTRS;
3819             } else {
3820                 if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3821                     ctxt->loadsubset -= XML_COMPLETE_ATTRS;
3822             }
3823             return(0);
3824         case XML_PARSER_VALIDATE:
3825             if (value != 0) {
3826                 ctxt->validate = 1;
3827                 reader->validate = XML_TEXTREADER_VALIDATE_DTD;
3828             } else {
3829                 ctxt->validate = 0;
3830             }
3831             return(0);
3832         case XML_PARSER_SUBST_ENTITIES:
3833             if (value != 0) {
3834                 ctxt->replaceEntities = 1;
3835             } else {
3836                 ctxt->replaceEntities = 0;
3837             }
3838             return(0);
3839     }
3840     return(-1);
3841 }
3842
3843 /**
3844  * xmlTextReaderGetParserProp:
3845  * @reader:  the xmlTextReaderPtr used
3846  * @prop:  the xmlParserProperties to get
3847  *
3848  * Read the parser internal property.
3849  *
3850  * Returns the value, usually 0 or 1, or -1 in case of error.
3851  */
3852 int
3853 xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
3854     xmlParserProperties p = (xmlParserProperties) prop;
3855     xmlParserCtxtPtr ctxt;
3856
3857     if ((reader == NULL) || (reader->ctxt == NULL))
3858         return(-1);
3859     ctxt = reader->ctxt;
3860
3861     switch (p) {
3862         case XML_PARSER_LOADDTD:
3863             if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
3864                 return(1);
3865             return(0);
3866         case XML_PARSER_DEFAULTATTRS:
3867             if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
3868                 return(1);
3869             return(0);
3870         case XML_PARSER_VALIDATE:
3871             return(reader->validate);
3872         case XML_PARSER_SUBST_ENTITIES:
3873             return(ctxt->replaceEntities);
3874     }
3875     return(-1);
3876 }
3877
3878
3879 /**
3880  * xmlTextReaderGetParserLineNumber:
3881  * @reader: the user data (XML reader context)
3882  *
3883  * Provide the line number of the current parsing point.
3884  *
3885  * Returns an int or 0 if not available
3886  */
3887 int
3888 xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader)
3889 {
3890     if ((reader == NULL) || (reader->ctxt == NULL) ||
3891         (reader->ctxt->input == NULL)) {
3892         return (0);
3893     }
3894     return (reader->ctxt->input->line);
3895 }
3896
3897 /**
3898  * xmlTextReaderGetParserColumnNumber:
3899  * @reader: the user data (XML reader context)
3900  *
3901  * Provide the column number of the current parsing point.
3902  *
3903  * Returns an int or 0 if not available
3904  */
3905 int
3906 xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader)
3907 {
3908     if ((reader == NULL) || (reader->ctxt == NULL) ||
3909         (reader->ctxt->input == NULL)) {
3910         return (0);
3911     }
3912     return (reader->ctxt->input->col);
3913 }
3914
3915 /**
3916  * xmlTextReaderCurrentNode:
3917  * @reader:  the xmlTextReaderPtr used
3918  *
3919  * Hacking interface allowing to get the xmlNodePtr correponding to the
3920  * current node being accessed by the xmlTextReader. This is dangerous
3921  * because the underlying node may be destroyed on the next Reads.
3922  *
3923  * Returns the xmlNodePtr or NULL in case of error.
3924  */
3925 xmlNodePtr
3926 xmlTextReaderCurrentNode(xmlTextReaderPtr reader) {
3927     if (reader == NULL)
3928         return(NULL);
3929
3930     if (reader->curnode != NULL)
3931         return(reader->curnode);
3932     return(reader->node);
3933 }
3934
3935 /**
3936  * xmlTextReaderPreserve:
3937  * @reader:  the xmlTextReaderPtr used
3938  *
3939  * This tells the XML Reader to preserve the current node.
3940  * The caller must also use xmlTextReaderCurrentDoc() to
3941  * keep an handle on the resulting document once parsing has finished
3942  *
3943  * Returns the xmlNodePtr or NULL in case of error.
3944  */
3945 xmlNodePtr
3946 xmlTextReaderPreserve(xmlTextReaderPtr reader) {
3947     xmlNodePtr cur, parent;
3948
3949     if (reader == NULL)
3950         return(NULL);
3951
3952     if (reader->curnode != NULL)
3953         cur = reader->curnode;
3954     else
3955         cur = reader->node;
3956     if (cur == NULL)
3957         return(NULL);
3958
3959     if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
3960         cur->extra |= NODE_IS_PRESERVED;
3961         cur->extra |= NODE_IS_SPRESERVED;
3962     }
3963     reader->preserves++;
3964
3965     parent = cur->parent;;
3966     while (parent != NULL) {
3967         if (parent->type == XML_ELEMENT_NODE)
3968             parent->extra |= NODE_IS_PRESERVED;
3969         parent = parent->parent;
3970     }
3971     return(cur);
3972 }
3973
3974 #ifdef LIBXML_PATTERN_ENABLED
3975 /**
3976  * xmlTextReaderPreservePattern:
3977  * @reader:  the xmlTextReaderPtr used
3978  * @pattern:  an XPath subset pattern
3979  * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
3980  *
3981  * This tells the XML Reader to preserve all nodes matched by the
3982  * pattern. The caller must also use xmlTextReaderCurrentDoc() to
3983  * keep an handle on the resulting document once parsing has finished
3984  *
3985  * Returns a non-negative number in case of success and -1 in case of error
3986  */
3987 int
3988 xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern,
3989                              const xmlChar **namespaces)
3990 {
3991     xmlPatternPtr comp;
3992
3993     if ((reader == NULL) || (pattern == NULL))
3994         return(-1);
3995
3996     comp = xmlPatterncompile(pattern, reader->dict, 0, namespaces);
3997     if (comp == NULL)
3998         return(-1);
3999
4000     if (reader->patternMax <= 0) {
4001         reader->patternMax = 4;
4002         reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax *
4003                                               sizeof(reader->patternTab[0]));
4004         if (reader->patternTab == NULL) {
4005             xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
4006             return (-1);
4007         }
4008     }
4009     if (reader->patternNr >= reader->patternMax) {
4010         xmlPatternPtr *tmp;
4011         reader->patternMax *= 2;
4012         tmp = (xmlPatternPtr *) xmlRealloc(reader->patternTab,
4013                                       reader->patternMax *
4014                                       sizeof(reader->patternTab[0]));
4015         if (tmp == NULL) {
4016             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4017             reader->patternMax /= 2;
4018             return (-1);
4019         }
4020         reader->patternTab = tmp;
4021     }
4022     reader->patternTab[reader->patternNr] = comp;
4023     return(reader->patternNr++);
4024 }
4025 #endif
4026
4027 /**
4028  * xmlTextReaderCurrentDoc:
4029  * @reader:  the xmlTextReaderPtr used
4030  *
4031  * Hacking interface allowing to get the xmlDocPtr correponding to the
4032  * current document being accessed by the xmlTextReader.
4033  * NOTE: as a result of this call, the reader will not destroy the
4034  *       associated XML document and calling xmlFreeDoc() on the result
4035  *       is needed once the reader parsing has finished.
4036  *
4037  * Returns the xmlDocPtr or NULL in case of error.
4038  */
4039 xmlDocPtr
4040 xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
4041     if (reader == NULL)
4042         return(NULL);
4043     if (reader->doc != NULL)
4044         return(reader->doc);
4045     if ((reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL))
4046         return(NULL);
4047
4048     reader->preserve = 1;
4049     return(reader->ctxt->myDoc);
4050 }
4051
4052 #ifdef LIBXML_SCHEMAS_ENABLED
4053 static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0);
4054
4055 static void XMLCDECL
4056 xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4057
4058 static void XMLCDECL
4059 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4060
4061 static void XMLCDECL
4062 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4063
4064 static void XMLCDECL
4065 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3);
4066
4067 static void XMLCDECL
4068 xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...)
4069 {
4070     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4071
4072     char *str;
4073
4074     va_list ap;
4075
4076     va_start(ap, msg);
4077     str = xmlTextReaderBuildMessage(msg, ap);
4078     if (!reader->errorFunc) {
4079         xmlTextReaderValidityError(ctx, "%s", str);
4080     } else {
4081         reader->errorFunc(reader->errorFuncArg, str,
4082                           XML_PARSER_SEVERITY_VALIDITY_ERROR,
4083                           NULL /* locator */ );
4084     }
4085     if (str != NULL)
4086         xmlFree(str);
4087     va_end(ap);
4088 }
4089
4090 static void XMLCDECL
4091 xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...)
4092 {
4093     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx;
4094
4095     char *str;
4096
4097     va_list ap;
4098
4099     va_start(ap, msg);
4100     str = xmlTextReaderBuildMessage(msg, ap);
4101     if (!reader->errorFunc) {
4102         xmlTextReaderValidityWarning(ctx, "%s", str);
4103     } else {
4104         reader->errorFunc(reader->errorFuncArg, str,
4105                           XML_PARSER_SEVERITY_VALIDITY_WARNING,
4106                           NULL /* locator */ );
4107     }
4108     if (str != NULL)
4109         xmlFree(str);
4110     va_end(ap);
4111 }
4112
4113 static void
4114   xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error);
4115
4116 static void
4117 xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error)
4118 {
4119     xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
4120
4121     if (reader->sErrorFunc) {
4122         reader->sErrorFunc(reader->errorFuncArg, error);
4123     } else {
4124         xmlTextReaderStructuredError(reader, error);
4125     }
4126 }
4127 /**
4128  * xmlTextReaderRelaxNGSetSchema:
4129  * @reader:  the xmlTextReaderPtr used
4130  * @schema:  a precompiled RelaxNG schema
4131  *
4132  * Use RelaxNG to validate the document as it is processed.
4133  * Activation is only possible before the first Read().
4134  * if @schema is NULL, then RelaxNG validation is desactivated.
4135  @ The @schema should not be freed until the reader is deallocated
4136  * or its use has been deactivated.
4137  *
4138  * Returns 0 in case the RelaxNG validation could be (des)activated and
4139  *         -1 in case of error.
4140  */
4141 int
4142 xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
4143     if (reader == NULL)
4144         return(-1);
4145     if (schema == NULL) {
4146         if (reader->rngSchemas != NULL) {
4147             xmlRelaxNGFree(reader->rngSchemas);
4148             reader->rngSchemas = NULL;
4149         }
4150         if (reader->rngValidCtxt != NULL) {
4151             if (! reader->rngPreserveCtxt)
4152                 xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4153             reader->rngValidCtxt = NULL;
4154         }
4155         reader->rngPreserveCtxt = 0;
4156         return(0);
4157     }
4158     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4159         return(-1);
4160     if (reader->rngSchemas != NULL) {
4161         xmlRelaxNGFree(reader->rngSchemas);
4162         reader->rngSchemas = NULL;
4163     }
4164     if (reader->rngValidCtxt != NULL) {
4165         if (! reader->rngPreserveCtxt)
4166             xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4167         reader->rngValidCtxt = NULL;
4168     }
4169     reader->rngPreserveCtxt = 0;
4170     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
4171     if (reader->rngValidCtxt == NULL)
4172         return(-1);
4173     if (reader->errorFunc != NULL) {
4174         xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4175                         xmlTextReaderValidityErrorRelay,
4176                         xmlTextReaderValidityWarningRelay,
4177                         reader);
4178     }
4179         if (reader->sErrorFunc != NULL) {
4180                 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4181                         xmlTextReaderValidityStructuredRelay,
4182                         reader);
4183     }
4184     reader->rngValidErrors = 0;
4185     reader->rngFullNode = NULL;
4186     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4187     return(0);
4188 }
4189
4190 /**
4191  * xmlTextReaderLocator:
4192  * @ctx: the xmlTextReaderPtr used
4193  * @file: returned file information
4194  * @line: returned line information
4195  *
4196  * Internal locator function for the readers
4197  *
4198  * Returns 0 in case the Schema validation could be (des)activated and
4199  *         -1 in case of error.
4200  */
4201 static int
4202 xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
4203     xmlTextReaderPtr reader;
4204
4205     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
4206         return(-1);
4207
4208     if (file != NULL)
4209         *file = NULL;
4210     if (line != NULL)
4211         *line = 0;
4212
4213     reader = (xmlTextReaderPtr) ctx;
4214     if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
4215         if (file != NULL)
4216             *file = reader->ctxt->input->filename;
4217         if (line != NULL)
4218             *line = reader->ctxt->input->line;
4219         return(0);
4220     }
4221     if (reader->node != NULL) {
4222         long res;
4223         int ret = 0;
4224
4225         if (line != NULL) {
4226             res = xmlGetLineNo(reader->node);
4227             if (res > 0)
4228                 *line = (unsigned long) res;
4229             else
4230                 ret = -1;
4231         }
4232         if (file != NULL) {
4233             xmlDocPtr doc = reader->node->doc;
4234             if ((doc != NULL) && (doc->URL != NULL))
4235                 *file = (const char *) doc->URL;
4236             else
4237                 ret = -1;
4238         }
4239         return(ret);
4240     }
4241     return(-1);
4242 }
4243
4244 /**
4245  * xmlTextReaderSetSchema:
4246  * @reader:  the xmlTextReaderPtr used
4247  * @schema:  a precompiled Schema schema
4248  *
4249  * Use XSD Schema to validate the document as it is processed.
4250  * Activation is only possible before the first Read().
4251  * if @schema is NULL, then Schema validation is desactivated.
4252  @ The @schema should not be freed until the reader is deallocated
4253  * or its use has been deactivated.
4254  *
4255  * Returns 0 in case the Schema validation could be (des)activated and
4256  *         -1 in case of error.
4257  */
4258 int
4259 xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
4260     if (reader == NULL)
4261         return(-1);
4262     if (schema == NULL) {
4263         if (reader->xsdPlug != NULL) {
4264             xmlSchemaSAXUnplug(reader->xsdPlug);
4265             reader->xsdPlug = NULL;
4266         }
4267         if (reader->xsdValidCtxt != NULL) {
4268             if (! reader->xsdPreserveCtxt)
4269                 xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4270             reader->xsdValidCtxt = NULL;
4271         }
4272         reader->xsdPreserveCtxt = 0;
4273         if (reader->xsdSchemas != NULL) {
4274             xmlSchemaFree(reader->xsdSchemas);
4275             reader->xsdSchemas = NULL;
4276         }
4277         return(0);
4278     }
4279     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
4280         return(-1);
4281     if (reader->xsdPlug != NULL) {
4282         xmlSchemaSAXUnplug(reader->xsdPlug);
4283         reader->xsdPlug = NULL;
4284     }
4285     if (reader->xsdValidCtxt != NULL) {
4286         if (! reader->xsdPreserveCtxt)
4287             xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4288         reader->xsdValidCtxt = NULL;
4289     }
4290     reader->xsdPreserveCtxt = 0;
4291     if (reader->xsdSchemas != NULL) {
4292         xmlSchemaFree(reader->xsdSchemas);
4293         reader->xsdSchemas = NULL;
4294     }
4295     reader->xsdValidCtxt = xmlSchemaNewValidCtxt(schema);
4296     if (reader->xsdValidCtxt == NULL) {
4297         xmlSchemaFree(reader->xsdSchemas);
4298         reader->xsdSchemas = NULL;
4299         return(-1);
4300     }
4301     reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4302                                        &(reader->ctxt->sax),
4303                                        &(reader->ctxt->userData));
4304     if (reader->xsdPlug == NULL) {
4305         xmlSchemaFree(reader->xsdSchemas);
4306         reader->xsdSchemas = NULL;
4307         xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4308         reader->xsdValidCtxt = NULL;
4309         return(-1);
4310     }
4311     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4312                                 xmlTextReaderLocator,
4313                                 (void *) reader);
4314
4315     if (reader->errorFunc != NULL) {
4316         xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4317                         xmlTextReaderValidityErrorRelay,
4318                         xmlTextReaderValidityWarningRelay,
4319                         reader);
4320     }
4321         if (reader->sErrorFunc != NULL) {
4322                 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4323                         xmlTextReaderValidityStructuredRelay,
4324                         reader);
4325     }
4326     reader->xsdValidErrors = 0;
4327     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4328     return(0);
4329 }
4330
4331 /**
4332  * xmlTextReaderRelaxNGValidateInternal:
4333  * @reader:  the xmlTextReaderPtr used
4334  * @rng:  the path to a RelaxNG schema or NULL
4335  * @ctxt: the RelaxNG schema validation context or NULL
4336  * @options: options (not yet used)
4337  *
4338  * Use RelaxNG to validate the document as it is processed.
4339  * Activation is only possible before the first Read().
4340  * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
4341  *
4342  * Returns 0 in case the RelaxNG validation could be (de)activated and
4343  *         -1 in case of error.
4344  */
4345 static int
4346 xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
4347                                      const char *rng,
4348                                      xmlRelaxNGValidCtxtPtr ctxt,
4349                                      int options ATTRIBUTE_UNUSED)
4350 {
4351     if (reader == NULL)
4352         return(-1);
4353
4354     if ((rng != NULL) && (ctxt != NULL))
4355         return (-1);
4356
4357     if (((rng != NULL) || (ctxt != NULL)) &&
4358         ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4359          (reader->ctxt == NULL)))
4360         return(-1);
4361
4362     /* Cleanup previous validation stuff. */
4363     if (reader->rngValidCtxt != NULL) {
4364         if ( !reader->rngPreserveCtxt)
4365             xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
4366         reader->rngValidCtxt = NULL;
4367     }
4368     reader->rngPreserveCtxt = 0;
4369     if (reader->rngSchemas != NULL) {
4370         xmlRelaxNGFree(reader->rngSchemas);
4371         reader->rngSchemas = NULL;
4372     }
4373
4374     if ((rng == NULL) && (ctxt == NULL)) {
4375         /* We just want to deactivate the validation, so get out. */
4376         return(0);
4377     }
4378
4379
4380     if (rng != NULL) {
4381         xmlRelaxNGParserCtxtPtr pctxt;
4382         /* Parse the schema and create validation environment. */
4383
4384         pctxt = xmlRelaxNGNewParserCtxt(rng);
4385         if (reader->errorFunc != NULL) {
4386             xmlRelaxNGSetParserErrors(pctxt,
4387                 xmlTextReaderValidityErrorRelay,
4388                 xmlTextReaderValidityWarningRelay,
4389                 reader);
4390         }
4391         if (reader->sErrorFunc != NULL) {
4392             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4393                 xmlTextReaderValidityStructuredRelay,
4394                 reader);
4395         }
4396         reader->rngSchemas = xmlRelaxNGParse(pctxt);
4397         xmlRelaxNGFreeParserCtxt(pctxt);
4398         if (reader->rngSchemas == NULL)
4399             return(-1);
4400         reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
4401         if (reader->rngValidCtxt == NULL) {
4402             xmlRelaxNGFree(reader->rngSchemas);
4403             reader->rngSchemas = NULL;
4404             return(-1);
4405         }
4406     } else {
4407         /* Use the given validation context. */
4408         reader->rngValidCtxt = ctxt;
4409         reader->rngPreserveCtxt = 1;
4410     }
4411     /*
4412     * Redirect the validation context's error channels to use
4413     * the reader channels.
4414     * TODO: In case the user provides the validation context we
4415     *   could make this redirection optional.
4416     */
4417     if (reader->errorFunc != NULL) {
4418         xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4419                          xmlTextReaderValidityErrorRelay,
4420                          xmlTextReaderValidityWarningRelay,
4421                          reader);
4422     }
4423         if (reader->sErrorFunc != NULL) {
4424                 xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
4425                         xmlTextReaderValidityStructuredRelay,
4426                         reader);
4427     }
4428     reader->rngValidErrors = 0;
4429     reader->rngFullNode = NULL;
4430     reader->validate = XML_TEXTREADER_VALIDATE_RNG;
4431     return(0);
4432 }
4433
4434 /**
4435  * xmlTextReaderSchemaValidateInternal:
4436  * @reader:  the xmlTextReaderPtr used
4437  * @xsd:  the path to a W3C XSD schema or NULL
4438  * @ctxt: the XML Schema validation context or NULL
4439  * @options: options (not used yet)
4440  *
4441  * Validate the document as it is processed using XML Schema.
4442  * Activation is only possible before the first Read().
4443  * If both @xsd and @ctxt are NULL then XML Schema validation is deactivated.
4444  *
4445  * Returns 0 in case the schemas validation could be (de)activated and
4446  *         -1 in case of error.
4447  */
4448 static int
4449 xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
4450                                     const char *xsd,
4451                                     xmlSchemaValidCtxtPtr ctxt,
4452                                     int options ATTRIBUTE_UNUSED)
4453 {
4454     if (reader == NULL)
4455         return(-1);
4456
4457     if ((xsd != NULL) && (ctxt != NULL))
4458         return(-1);
4459
4460     if (((xsd != NULL) || (ctxt != NULL)) &&
4461         ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
4462         (reader->ctxt == NULL)))
4463         return(-1);
4464
4465     /* Cleanup previous validation stuff. */
4466     if (reader->xsdPlug != NULL) {
4467         xmlSchemaSAXUnplug(reader->xsdPlug);
4468         reader->xsdPlug = NULL;
4469     }
4470     if (reader->xsdValidCtxt != NULL) {
4471         if (! reader->xsdPreserveCtxt)
4472             xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4473         reader->xsdValidCtxt = NULL;
4474     }
4475     reader->xsdPreserveCtxt = 0;
4476     if (reader->xsdSchemas != NULL) {
4477         xmlSchemaFree(reader->xsdSchemas);
4478         reader->xsdSchemas = NULL;
4479     }
4480
4481     if ((xsd == NULL) && (ctxt == NULL)) {
4482         /* We just want to deactivate the validation, so get out. */
4483         return(0);
4484     }
4485
4486     if (xsd != NULL) {
4487         xmlSchemaParserCtxtPtr pctxt;
4488         /* Parse the schema and create validation environment. */
4489         pctxt = xmlSchemaNewParserCtxt(xsd);
4490         if (reader->errorFunc != NULL) {
4491             xmlSchemaSetParserErrors(pctxt,
4492                 xmlTextReaderValidityErrorRelay,
4493                 xmlTextReaderValidityWarningRelay,
4494                 reader);
4495         }
4496         reader->xsdSchemas = xmlSchemaParse(pctxt);
4497         xmlSchemaFreeParserCtxt(pctxt);
4498         if (reader->xsdSchemas == NULL)
4499             return(-1);
4500         reader->xsdValidCtxt = xmlSchemaNewValidCtxt(reader->xsdSchemas);
4501         if (reader->xsdValidCtxt == NULL) {
4502             xmlSchemaFree(reader->xsdSchemas);
4503             reader->xsdSchemas = NULL;
4504             return(-1);
4505         }
4506         reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4507             &(reader->ctxt->sax),
4508             &(reader->ctxt->userData));
4509         if (reader->xsdPlug == NULL) {
4510             xmlSchemaFree(reader->xsdSchemas);
4511             reader->xsdSchemas = NULL;
4512             xmlSchemaFreeValidCtxt(reader->xsdValidCtxt);
4513             reader->xsdValidCtxt = NULL;
4514             return(-1);
4515         }
4516     } else {
4517         /* Use the given validation context. */
4518         reader->xsdValidCtxt = ctxt;
4519         reader->xsdPreserveCtxt = 1;
4520         reader->xsdPlug = xmlSchemaSAXPlug(reader->xsdValidCtxt,
4521             &(reader->ctxt->sax),
4522             &(reader->ctxt->userData));
4523         if (reader->xsdPlug == NULL) {
4524             reader->xsdValidCtxt = NULL;
4525             reader->xsdPreserveCtxt = 0;
4526             return(-1);
4527         }
4528     }
4529     xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
4530                                 xmlTextReaderLocator,
4531                                 (void *) reader);
4532     /*
4533     * Redirect the validation context's error channels to use
4534     * the reader channels.
4535     * TODO: In case the user provides the validation context we
4536     *   could make this redirection optional.
4537     */
4538     if (reader->errorFunc != NULL) {
4539         xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4540                          xmlTextReaderValidityErrorRelay,
4541                          xmlTextReaderValidityWarningRelay,
4542                          reader);
4543     }
4544         if (reader->sErrorFunc != NULL) {
4545                 xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
4546                         xmlTextReaderValidityStructuredRelay,
4547                         reader);
4548     }
4549     reader->xsdValidErrors = 0;
4550     reader->validate = XML_TEXTREADER_VALIDATE_XSD;
4551     return(0);
4552 }
4553
4554 /**
4555  * xmlTextReaderSchemaValidateCtxt:
4556  * @reader:  the xmlTextReaderPtr used
4557  * @ctxt: the XML Schema validation context or NULL
4558  * @options: options (not used yet)
4559  *
4560  * Use W3C XSD schema context to validate the document as it is processed.
4561  * Activation is only possible before the first Read().
4562  * If @ctxt is NULL, then XML Schema validation is deactivated.
4563  *
4564  * Returns 0 in case the schemas validation could be (de)activated and
4565  *         -1 in case of error.
4566  */
4567 int
4568 xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader,
4569                                     xmlSchemaValidCtxtPtr ctxt,
4570                                     int options)
4571 {
4572     return(xmlTextReaderSchemaValidateInternal(reader, NULL, ctxt, options));
4573 }
4574
4575 /**
4576  * xmlTextReaderSchemaValidate:
4577  * @reader:  the xmlTextReaderPtr used
4578  * @xsd:  the path to a W3C XSD schema or NULL
4579  *
4580  * Use W3C XSD schema to validate the document as it is processed.
4581  * Activation is only possible before the first Read().
4582  * If @xsd is NULL, then XML Schema validation is deactivated.
4583  *
4584  * Returns 0 in case the schemas validation could be (de)activated and
4585  *         -1 in case of error.
4586  */
4587 int
4588 xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
4589 {
4590     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
4591 }
4592
4593 /**
4594  * xmlTextReaderRelaxNGValidateCtxt:
4595  * @reader:  the xmlTextReaderPtr used
4596  * @ctxt: the RelaxNG schema validation context or NULL
4597  * @options: options (not used yet)
4598  *
4599  * Use RelaxNG schema context to validate the document as it is processed.
4600  * Activation is only possible before the first Read().
4601  * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
4602  *
4603  * Returns 0 in case the schemas validation could be (de)activated and
4604  *         -1 in case of error.
4605  */
4606 int
4607 xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
4608                                  xmlRelaxNGValidCtxtPtr ctxt,
4609                                  int options)
4610 {
4611     return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
4612 }
4613
4614 /**
4615  * xmlTextReaderRelaxNGValidate:
4616  * @reader:  the xmlTextReaderPtr used
4617  * @rng:  the path to a RelaxNG schema or NULL
4618  *
4619  * Use RelaxNG schema to validate the document as it is processed.
4620  * Activation is only possible before the first Read().
4621  * If @rng is NULL, then RelaxNG schema validation is deactivated.
4622  *
4623  * Returns 0 in case the schemas validation could be (de)activated and
4624  *         -1 in case of error.
4625  */
4626 int
4627 xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
4628 {
4629     return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
4630 }
4631
4632 #endif
4633
4634 /**
4635  * xmlTextReaderIsNamespaceDecl:
4636  * @reader: the xmlTextReaderPtr used
4637  *
4638  * Determine whether the current node is a namespace declaration
4639  * rather than a regular attribute.
4640  *
4641  * Returns 1 if the current node is a namespace declaration, 0 if it
4642  * is a regular attribute or other type of node, or -1 in case of
4643  * error.
4644  */
4645 int
4646 xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader) {
4647     xmlNodePtr node;
4648     if (reader == NULL)
4649         return(-1);
4650     if (reader->node == NULL)
4651         return(-1);
4652     if (reader->curnode != NULL)
4653         node = reader->curnode;
4654     else
4655         node = reader->node;
4656
4657     if (XML_NAMESPACE_DECL == node->type)
4658         return(1);
4659     else
4660         return(0);
4661 }
4662
4663 /**
4664  * xmlTextReaderConstXmlVersion:
4665  * @reader:  the xmlTextReaderPtr used
4666  *
4667  * Determine the XML version of the document being read.
4668  *
4669  * Returns a string containing the XML version of the document or NULL
4670  * in case of error.  The string is deallocated with the reader.
4671  */
4672 const xmlChar *
4673 xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) {
4674     xmlDocPtr doc = NULL;
4675     if (reader == NULL)
4676         return(NULL);
4677     if (reader->doc != NULL)
4678         doc = reader->doc;
4679     else if (reader->ctxt != NULL)
4680         doc = reader->ctxt->myDoc;
4681     if (doc == NULL)
4682         return(NULL);
4683
4684     if (doc->version == NULL)
4685         return(NULL);
4686     else
4687       return(CONSTSTR(doc->version));
4688 }
4689
4690 /**
4691  * xmlTextReaderStandalone:
4692  * @reader:  the xmlTextReaderPtr used
4693  *
4694  * Determine the standalone status of the document being read.
4695  *
4696  * Returns 1 if the document was declared to be standalone, 0 if it
4697  * was declared to be not standalone, or -1 if the document did not
4698  * specify its standalone status or in case of error.
4699  */
4700 int
4701 xmlTextReaderStandalone(xmlTextReaderPtr reader) {
4702     xmlDocPtr doc = NULL;
4703     if (reader == NULL)
4704         return(-1);
4705     if (reader->doc != NULL)
4706         doc = reader->doc;
4707     else if (reader->ctxt != NULL)
4708         doc = reader->ctxt->myDoc;
4709     if (doc == NULL)
4710         return(-1);
4711
4712     return(doc->standalone);
4713 }
4714
4715 /************************************************************************
4716  *                                                                      *
4717  *                      Error Handling Extensions                       *
4718  *                                                                      *
4719  ************************************************************************/
4720
4721 /* helper to build a xmlMalloc'ed string from a format and va_list */
4722 static char *
4723 xmlTextReaderBuildMessage(const char *msg, va_list ap) {
4724     int size = 0;
4725     int chars;
4726     char *larger;
4727     char *str = NULL;
4728     va_list aq;
4729
4730     while (1) {
4731         VA_COPY(aq, ap);
4732         chars = vsnprintf(str, size, msg, aq);
4733         va_end(aq);
4734         if (chars < 0) {
4735             xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n");
4736             if (str)
4737                 xmlFree(str);
4738             return NULL;
4739         }
4740         if ((chars < size) || (size == MAX_ERR_MSG_SIZE))
4741             break;
4742         if (chars < MAX_ERR_MSG_SIZE)
4743         size = chars + 1;
4744         else
4745                 size = MAX_ERR_MSG_SIZE;
4746         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
4747             xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
4748             if (str)
4749                 xmlFree(str);
4750             return NULL;
4751         }
4752         str = larger;
4753     }
4754
4755     return str;
4756 }
4757
4758 /**
4759  * xmlTextReaderLocatorLineNumber:
4760  * @locator: the xmlTextReaderLocatorPtr used
4761  *
4762  * Obtain the line number for the given locator.
4763  *
4764  * Returns the line number or -1 in case of error.
4765  */
4766 int
4767 xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator) {
4768     /* we know that locator is a xmlParserCtxtPtr */
4769     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4770     int ret = -1;
4771
4772     if (locator == NULL)
4773         return(-1);
4774     if (ctx->node != NULL) {
4775         ret = xmlGetLineNo(ctx->node);
4776     }
4777     else {
4778         /* inspired from error.c */
4779         xmlParserInputPtr input;
4780         input = ctx->input;
4781         if ((input->filename == NULL) && (ctx->inputNr > 1))
4782             input = ctx->inputTab[ctx->inputNr - 2];
4783         if (input != NULL) {
4784             ret = input->line;
4785         }
4786         else {
4787             ret = -1;
4788         }
4789     }
4790
4791     return ret;
4792 }
4793
4794 /**
4795  * xmlTextReaderLocatorBaseURI:
4796  * @locator: the xmlTextReaderLocatorPtr used
4797  *
4798  * Obtain the base URI for the given locator.
4799  *
4800  * Returns the base URI or NULL in case of error,
4801  *    if non NULL it need to be freed by the caller.
4802  */
4803 xmlChar *
4804 xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) {
4805     /* we know that locator is a xmlParserCtxtPtr */
4806     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)locator;
4807     xmlChar *ret = NULL;
4808
4809     if (locator == NULL)
4810         return(NULL);
4811     if (ctx->node != NULL) {
4812         ret = xmlNodeGetBase(NULL,ctx->node);
4813     }
4814     else {
4815         /* inspired from error.c */
4816         xmlParserInputPtr input;
4817         input = ctx->input;
4818         if ((input->filename == NULL) && (ctx->inputNr > 1))
4819             input = ctx->inputTab[ctx->inputNr - 2];
4820         if (input != NULL) {
4821             ret = xmlStrdup(BAD_CAST input->filename);
4822         }
4823         else {
4824             ret = NULL;
4825         }
4826     }
4827
4828     return ret;
4829 }
4830
4831 static void
4832 xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity,
4833                           char *str)
4834 {
4835     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4836
4837     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4838
4839     if (str != NULL) {
4840         if (reader->errorFunc)
4841             reader->errorFunc(reader->errorFuncArg, str, severity,
4842                               (xmlTextReaderLocatorPtr) ctx);
4843         xmlFree(str);
4844     }
4845 }
4846
4847 static void
4848 xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error)
4849 {
4850     xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
4851
4852     xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private;
4853
4854     if (error && reader->sErrorFunc) {
4855         reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error);
4856     }
4857 }
4858
4859 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4860 xmlTextReaderError(void *ctxt, const char *msg, ...)
4861 {
4862     va_list ap;
4863
4864     va_start(ap, msg);
4865     xmlTextReaderGenericError(ctxt,
4866                               XML_PARSER_SEVERITY_ERROR,
4867                               xmlTextReaderBuildMessage(msg, ap));
4868     va_end(ap);
4869
4870 }
4871
4872 static void XMLCDECL LIBXML_ATTR_FORMAT(2,3)
4873 xmlTextReaderWarning(void *ctxt, const char *msg, ...)
4874 {
4875     va_list ap;
4876
4877     va_start(ap, msg);
4878     xmlTextReaderGenericError(ctxt,
4879                               XML_PARSER_SEVERITY_WARNING,
4880                               xmlTextReaderBuildMessage(msg, ap));
4881     va_end(ap);
4882 }
4883
4884 static void XMLCDECL
4885 xmlTextReaderValidityError(void *ctxt, const char *msg, ...)
4886 {
4887     va_list ap;
4888
4889     int len = xmlStrlen((const xmlChar *) msg);
4890
4891     if ((len > 1) && (msg[len - 2] != ':')) {
4892         /*
4893          * some callbacks only report locator information:
4894          * skip them (mimicking behaviour in error.c)
4895          */
4896         va_start(ap, msg);
4897         xmlTextReaderGenericError(ctxt,
4898                                   XML_PARSER_SEVERITY_VALIDITY_ERROR,
4899                                   xmlTextReaderBuildMessage(msg, ap));
4900         va_end(ap);
4901     }
4902 }
4903
4904 static void XMLCDECL
4905 xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...)
4906 {
4907     va_list ap;
4908
4909     int len = xmlStrlen((const xmlChar *) msg);
4910
4911     if ((len != 0) && (msg[len - 1] != ':')) {
4912         /*
4913          * some callbacks only report locator information:
4914          * skip them (mimicking behaviour in error.c)
4915          */
4916         va_start(ap, msg);
4917         xmlTextReaderGenericError(ctxt,
4918                                   XML_PARSER_SEVERITY_VALIDITY_WARNING,
4919                                   xmlTextReaderBuildMessage(msg, ap));
4920         va_end(ap);
4921     }
4922 }
4923
4924 /**
4925  * xmlTextReaderSetErrorHandler:
4926  * @reader:  the xmlTextReaderPtr used
4927  * @f:  the callback function to call on error and warnings
4928  * @arg:    a user argument to pass to the callback function
4929  *
4930  * Register a callback function that will be called on error and warnings.
4931  *
4932  * If @f is NULL, the default error and warning handlers are restored.
4933  */
4934 void
4935 xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
4936                              xmlTextReaderErrorFunc f, void *arg)
4937 {
4938     if (f != NULL) {
4939         reader->ctxt->sax->error = xmlTextReaderError;
4940         reader->ctxt->sax->serror = NULL;
4941         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
4942         reader->ctxt->sax->warning = xmlTextReaderWarning;
4943         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
4944         reader->errorFunc = f;
4945         reader->sErrorFunc = NULL;
4946         reader->errorFuncArg = arg;
4947 #ifdef LIBXML_SCHEMAS_ENABLED
4948         if (reader->rngValidCtxt) {
4949             xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
4950                                      xmlTextReaderValidityErrorRelay,
4951                                      xmlTextReaderValidityWarningRelay,
4952                                      reader);
4953             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4954                                                reader);
4955         }
4956         if (reader->xsdValidCtxt) {
4957             xmlSchemaSetValidErrors(reader->xsdValidCtxt,
4958                                     xmlTextReaderValidityErrorRelay,
4959                                     xmlTextReaderValidityWarningRelay,
4960                                     reader);
4961             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4962                                               reader);
4963         }
4964 #endif
4965     } else {
4966         /* restore defaults */
4967         reader->ctxt->sax->error = xmlParserError;
4968         reader->ctxt->vctxt.error = xmlParserValidityError;
4969         reader->ctxt->sax->warning = xmlParserWarning;
4970         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
4971         reader->errorFunc = NULL;
4972         reader->sErrorFunc = NULL;
4973         reader->errorFuncArg = NULL;
4974 #ifdef LIBXML_SCHEMAS_ENABLED
4975         if (reader->rngValidCtxt) {
4976             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
4977                                      reader);
4978             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
4979                                                reader);
4980         }
4981         if (reader->xsdValidCtxt) {
4982             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
4983                                     reader);
4984             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
4985                                               reader);
4986         }
4987 #endif
4988     }
4989 }
4990
4991 /**
4992 * xmlTextReaderSetStructuredErrorHandler:
4993  * @reader:  the xmlTextReaderPtr used
4994  * @f:  the callback function to call on error and warnings
4995  * @arg:    a user argument to pass to the callback function
4996  *
4997  * Register a callback function that will be called on error and warnings.
4998  *
4999  * If @f is NULL, the default error and warning handlers are restored.
5000  */
5001 void
5002 xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader,
5003                                        xmlStructuredErrorFunc f, void *arg)
5004 {
5005     if (f != NULL) {
5006         reader->ctxt->sax->error = NULL;
5007         reader->ctxt->sax->serror = xmlTextReaderStructuredError;
5008         reader->ctxt->vctxt.error = xmlTextReaderValidityError;
5009         reader->ctxt->sax->warning = xmlTextReaderWarning;
5010         reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
5011         reader->sErrorFunc = f;
5012         reader->errorFunc = NULL;
5013         reader->errorFuncArg = arg;
5014 #ifdef LIBXML_SCHEMAS_ENABLED
5015         if (reader->rngValidCtxt) {
5016             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5017                                      reader);
5018             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
5019                                         xmlTextReaderValidityStructuredRelay,
5020                                                reader);
5021         }
5022         if (reader->xsdValidCtxt) {
5023             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5024                                     reader);
5025             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt,
5026                                        xmlTextReaderValidityStructuredRelay,
5027                                               reader);
5028         }
5029 #endif
5030     } else {
5031         /* restore defaults */
5032         reader->ctxt->sax->error = xmlParserError;
5033         reader->ctxt->sax->serror = NULL;
5034         reader->ctxt->vctxt.error = xmlParserValidityError;
5035         reader->ctxt->sax->warning = xmlParserWarning;
5036         reader->ctxt->vctxt.warning = xmlParserValidityWarning;
5037         reader->errorFunc = NULL;
5038         reader->sErrorFunc = NULL;
5039         reader->errorFuncArg = NULL;
5040 #ifdef LIBXML_SCHEMAS_ENABLED
5041         if (reader->rngValidCtxt) {
5042             xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL,
5043                                      reader);
5044             xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL,
5045                                                reader);
5046         }
5047         if (reader->xsdValidCtxt) {
5048             xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL,
5049                                     reader);
5050             xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL,
5051                                               reader);
5052         }
5053 #endif
5054     }
5055 }
5056
5057 /**
5058  * xmlTextReaderIsValid:
5059  * @reader:  the xmlTextReaderPtr used
5060  *
5061  * Retrieve the validity status from the parser context
5062  *
5063  * Returns the flag value 1 if valid, 0 if no, and -1 in case of error
5064  */
5065 int
5066 xmlTextReaderIsValid(xmlTextReaderPtr reader)
5067 {
5068     if (reader == NULL)
5069         return (-1);
5070 #ifdef LIBXML_SCHEMAS_ENABLED
5071     if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
5072         return (reader->rngValidErrors == 0);
5073     if (reader->validate == XML_TEXTREADER_VALIDATE_XSD)
5074         return (reader->xsdValidErrors == 0);
5075 #endif
5076     if ((reader->ctxt != NULL) && (reader->ctxt->validate == 1))
5077         return (reader->ctxt->valid);
5078     return (0);
5079 }
5080
5081 /**
5082  * xmlTextReaderGetErrorHandler:
5083  * @reader:  the xmlTextReaderPtr used
5084  * @f:  the callback function or NULL is no callback has been registered
5085  * @arg:    a user argument
5086  *
5087  * Retrieve the error callback function and user argument.
5088  */
5089 void
5090 xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
5091                              xmlTextReaderErrorFunc * f, void **arg)
5092 {
5093     if (f != NULL)
5094         *f = reader->errorFunc;
5095     if (arg != NULL)
5096         *arg = reader->errorFuncArg;
5097 }
5098 /************************************************************************
5099  *                                                                      *
5100  *      New set (2.6.0) of simpler and more flexible APIs               *
5101  *                                                                      *
5102  ************************************************************************/
5103
5104 /**
5105  * xmlTextReaderSetup:
5106  * @reader:  an XML reader
5107  * @input: xmlParserInputBufferPtr used to feed the reader, will
5108  *         be destroyed with it.
5109  * @URL:  the base URL to use for the document
5110  * @encoding:  the document encoding, or NULL
5111  * @options:  a combination of xmlParserOption
5112  *
5113  * Setup an XML reader with new options
5114  *
5115  * Returns 0 in case of success and -1 in case of error.
5116  */
5117 int
5118 xmlTextReaderSetup(xmlTextReaderPtr reader,
5119                    xmlParserInputBufferPtr input, const char *URL,
5120                    const char *encoding, int options)
5121 {
5122     if (reader == NULL) {
5123         if (input != NULL)
5124             xmlFreeParserInputBuffer(input);
5125         return (-1);
5126     }
5127
5128     /*
5129      * we force the generation of compact text nodes on the reader
5130      * since usr applications should never modify the tree
5131      */
5132     options |= XML_PARSE_COMPACT;
5133
5134     reader->doc = NULL;
5135     reader->entNr = 0;
5136     reader->parserFlags = options;
5137     reader->validate = XML_TEXTREADER_NOT_VALIDATE;
5138     if ((input != NULL) && (reader->input != NULL) &&
5139         (reader->allocs & XML_TEXTREADER_INPUT)) {
5140         xmlFreeParserInputBuffer(reader->input);
5141         reader->input = NULL;
5142         reader->allocs -= XML_TEXTREADER_INPUT;
5143     }
5144     if (input != NULL) {
5145         reader->input = input;
5146         reader->allocs |= XML_TEXTREADER_INPUT;
5147     }
5148     if (reader->buffer == NULL)
5149         reader->buffer = xmlBufCreateSize(100);
5150     if (reader->buffer == NULL) {
5151         xmlGenericError(xmlGenericErrorContext,
5152                         "xmlTextReaderSetup : malloc failed\n");
5153         return (-1);
5154     }
5155     /* no operation on a reader should require a huge buffer */
5156     xmlBufSetAllocationScheme(reader->buffer,
5157                               XML_BUFFER_ALLOC_BOUNDED);
5158     if (reader->sax == NULL)
5159         reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
5160     if (reader->sax == NULL) {
5161         xmlGenericError(xmlGenericErrorContext,
5162                         "xmlTextReaderSetup : malloc failed\n");
5163         return (-1);
5164     }
5165     xmlSAXVersion(reader->sax, 2);
5166     reader->startElement = reader->sax->startElement;
5167     reader->sax->startElement = xmlTextReaderStartElement;
5168     reader->endElement = reader->sax->endElement;
5169     reader->sax->endElement = xmlTextReaderEndElement;
5170 #ifdef LIBXML_SAX1_ENABLED
5171     if (reader->sax->initialized == XML_SAX2_MAGIC) {
5172 #endif /* LIBXML_SAX1_ENABLED */
5173         reader->startElementNs = reader->sax->startElementNs;
5174         reader->sax->startElementNs = xmlTextReaderStartElementNs;
5175         reader->endElementNs = reader->sax->endElementNs;
5176         reader->sax->endElementNs = xmlTextReaderEndElementNs;
5177 #ifdef LIBXML_SAX1_ENABLED
5178     } else {
5179         reader->startElementNs = NULL;
5180         reader->endElementNs = NULL;
5181     }
5182 #endif /* LIBXML_SAX1_ENABLED */
5183     reader->characters = reader->sax->characters;
5184     reader->sax->characters = xmlTextReaderCharacters;
5185     reader->sax->ignorableWhitespace = xmlTextReaderCharacters;
5186     reader->cdataBlock = reader->sax->cdataBlock;
5187     reader->sax->cdataBlock = xmlTextReaderCDataBlock;
5188
5189     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5190     reader->node = NULL;
5191     reader->curnode = NULL;
5192     if (input != NULL) {
5193         if (xmlBufUse(reader->input->buffer) < 4) {
5194             xmlParserInputBufferRead(input, 4);
5195         }
5196         if (reader->ctxt == NULL) {
5197             if (xmlBufUse(reader->input->buffer) >= 4) {
5198                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
5199                        (const char *) xmlBufContent(reader->input->buffer),
5200                                       4, URL);
5201                 reader->base = 0;
5202                 reader->cur = 4;
5203             } else {
5204                 reader->ctxt =
5205                     xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL);
5206                 reader->base = 0;
5207                 reader->cur = 0;
5208             }
5209         } else {
5210             xmlParserInputPtr inputStream;
5211             xmlParserInputBufferPtr buf;
5212             xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
5213
5214             xmlCtxtReset(reader->ctxt);
5215             buf = xmlAllocParserInputBuffer(enc);
5216             if (buf == NULL) return(-1);
5217             inputStream = xmlNewInputStream(reader->ctxt);
5218             if (inputStream == NULL) {
5219                 xmlFreeParserInputBuffer(buf);
5220                 return(-1);
5221             }
5222
5223             if (URL == NULL)
5224                 inputStream->filename = NULL;
5225             else
5226                 inputStream->filename = (char *)
5227                     xmlCanonicPath((const xmlChar *) URL);
5228             inputStream->buf = buf;
5229             xmlBufResetInput(buf->buffer, inputStream);
5230
5231             inputPush(reader->ctxt, inputStream);
5232             reader->cur = 0;
5233         }
5234         if (reader->ctxt == NULL) {
5235             xmlGenericError(xmlGenericErrorContext,
5236                             "xmlTextReaderSetup : malloc failed\n");
5237             return (-1);
5238         }
5239     }
5240     if (reader->dict != NULL) {
5241         if (reader->ctxt->dict != NULL) {
5242             if (reader->dict != reader->ctxt->dict) {
5243                 xmlDictFree(reader->dict);
5244                 reader->dict = reader->ctxt->dict;
5245             }
5246         } else {
5247             reader->ctxt->dict = reader->dict;
5248         }
5249     } else {
5250         if (reader->ctxt->dict == NULL)
5251             reader->ctxt->dict = xmlDictCreate();
5252         reader->dict = reader->ctxt->dict;
5253     }
5254     reader->ctxt->_private = reader;
5255     reader->ctxt->linenumbers = 1;
5256     reader->ctxt->dictNames = 1;
5257     /*
5258      * use the parser dictionary to allocate all elements and attributes names
5259      */
5260     reader->ctxt->docdict = 1;
5261     reader->ctxt->parseMode = XML_PARSE_READER;
5262
5263 #ifdef LIBXML_XINCLUDE_ENABLED
5264     if (reader->xincctxt != NULL) {
5265         xmlXIncludeFreeContext(reader->xincctxt);
5266         reader->xincctxt = NULL;
5267     }
5268     if (options & XML_PARSE_XINCLUDE) {
5269         reader->xinclude = 1;
5270         reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1);
5271         options -= XML_PARSE_XINCLUDE;
5272     } else
5273         reader->xinclude = 0;
5274     reader->in_xinclude = 0;
5275 #endif
5276 #ifdef LIBXML_PATTERN_ENABLED
5277     if (reader->patternTab == NULL) {
5278         reader->patternNr = 0;
5279         reader->patternMax = 0;
5280     }
5281     while (reader->patternNr > 0) {
5282         reader->patternNr--;
5283         if (reader->patternTab[reader->patternNr] != NULL) {
5284             xmlFreePattern(reader->patternTab[reader->patternNr]);
5285             reader->patternTab[reader->patternNr] = NULL;
5286         }
5287     }
5288 #endif
5289
5290     if (options & XML_PARSE_DTDVALID)
5291         reader->validate = XML_TEXTREADER_VALIDATE_DTD;
5292
5293     xmlCtxtUseOptions(reader->ctxt, options);
5294     if (encoding != NULL) {
5295         xmlCharEncodingHandlerPtr hdlr;
5296
5297         hdlr = xmlFindCharEncodingHandler(encoding);
5298         if (hdlr != NULL)
5299             xmlSwitchToEncoding(reader->ctxt, hdlr);
5300     }
5301     if ((URL != NULL) && (reader->ctxt->input != NULL) &&
5302         (reader->ctxt->input->filename == NULL))
5303         reader->ctxt->input->filename = (char *)
5304             xmlStrdup((const xmlChar *) URL);
5305
5306     reader->doc = NULL;
5307
5308     return (0);
5309 }
5310
5311 /**
5312  * xmlTextReaderByteConsumed:
5313  * @reader: an XML reader
5314  *
5315  * This function provides the current index of the parser used
5316  * by the reader, relative to the start of the current entity.
5317  * This function actually just wraps a call to xmlBytesConsumed()
5318  * for the parser context associated with the reader.
5319  * See xmlBytesConsumed() for more information.
5320  *
5321  * Returns the index in bytes from the beginning of the entity or -1
5322  *         in case the index could not be computed.
5323  */
5324 long
5325 xmlTextReaderByteConsumed(xmlTextReaderPtr reader) {
5326     if ((reader == NULL) || (reader->ctxt == NULL))
5327         return(-1);
5328     return(xmlByteConsumed(reader->ctxt));
5329 }
5330
5331
5332 /**
5333  * xmlReaderWalker:
5334  * @doc:  a preparsed document
5335  *
5336  * Create an xmltextReader for a preparsed document.
5337  *
5338  * Returns the new reader or NULL in case of error.
5339  */
5340 xmlTextReaderPtr
5341 xmlReaderWalker(xmlDocPtr doc)
5342 {
5343     xmlTextReaderPtr ret;
5344
5345     if (doc == NULL)
5346         return(NULL);
5347
5348     ret = xmlMalloc(sizeof(xmlTextReader));
5349     if (ret == NULL) {
5350         xmlGenericError(xmlGenericErrorContext,
5351                 "xmlNewTextReader : malloc failed\n");
5352         return(NULL);
5353     }
5354     memset(ret, 0, sizeof(xmlTextReader));
5355     ret->entNr = 0;
5356     ret->input = NULL;
5357     ret->mode = XML_TEXTREADER_MODE_INITIAL;
5358     ret->node = NULL;
5359     ret->curnode = NULL;
5360     ret->base = 0;
5361     ret->cur = 0;
5362     ret->allocs = XML_TEXTREADER_CTXT;
5363     ret->doc = doc;
5364     ret->state = XML_TEXTREADER_START;
5365     ret->dict = xmlDictCreate();
5366     return(ret);
5367 }
5368
5369 /**
5370  * xmlReaderForDoc:
5371  * @cur:  a pointer to a zero terminated string
5372  * @URL:  the base URL to use for the document
5373  * @encoding:  the document encoding, or NULL
5374  * @options:  a combination of xmlParserOption
5375  *
5376  * Create an xmltextReader for an XML in-memory document.
5377  * The parsing flags @options are a combination of xmlParserOption.
5378  *
5379  * Returns the new reader or NULL in case of error.
5380  */
5381 xmlTextReaderPtr
5382 xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding,
5383                 int options)
5384 {
5385     int len;
5386
5387     if (cur == NULL)
5388         return (NULL);
5389     len = xmlStrlen(cur);
5390
5391     return (xmlReaderForMemory
5392             ((const char *) cur, len, URL, encoding, options));
5393 }
5394
5395 /**
5396  * xmlReaderForFile:
5397  * @filename:  a file or URL
5398  * @encoding:  the document encoding, or NULL
5399  * @options:  a combination of xmlParserOption
5400  *
5401  * parse an XML file from the filesystem or the network.
5402  * The parsing flags @options are a combination of xmlParserOption.
5403  *
5404  * Returns the new reader or NULL in case of error.
5405  */
5406 xmlTextReaderPtr
5407 xmlReaderForFile(const char *filename, const char *encoding, int options)
5408 {
5409     xmlTextReaderPtr reader;
5410
5411     reader = xmlNewTextReaderFilename(filename);
5412     if (reader == NULL)
5413         return (NULL);
5414     xmlTextReaderSetup(reader, NULL, NULL, encoding, options);
5415     return (reader);
5416 }
5417
5418 /**
5419  * xmlReaderForMemory:
5420  * @buffer:  a pointer to a char array
5421  * @size:  the size of the array
5422  * @URL:  the base URL to use for the document
5423  * @encoding:  the document encoding, or NULL
5424  * @options:  a combination of xmlParserOption
5425  *
5426  * Create an xmltextReader for an XML in-memory document.
5427  * The parsing flags @options are a combination of xmlParserOption.
5428  *
5429  * Returns the new reader or NULL in case of error.
5430  */
5431 xmlTextReaderPtr
5432 xmlReaderForMemory(const char *buffer, int size, const char *URL,
5433                    const char *encoding, int options)
5434 {
5435     xmlTextReaderPtr reader;
5436     xmlParserInputBufferPtr buf;
5437
5438     buf = xmlParserInputBufferCreateStatic(buffer, size,
5439                                       XML_CHAR_ENCODING_NONE);
5440     if (buf == NULL) {
5441         return (NULL);
5442     }
5443     reader = xmlNewTextReader(buf, URL);
5444     if (reader == NULL) {
5445         xmlFreeParserInputBuffer(buf);
5446         return (NULL);
5447     }
5448     reader->allocs |= XML_TEXTREADER_INPUT;
5449     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5450     return (reader);
5451 }
5452
5453 /**
5454  * xmlReaderForFd:
5455  * @fd:  an open file descriptor
5456  * @URL:  the base URL to use for the document
5457  * @encoding:  the document encoding, or NULL
5458  * @options:  a combination of xmlParserOption
5459  *
5460  * Create an xmltextReader for an XML from a file descriptor.
5461  * The parsing flags @options are a combination of xmlParserOption.
5462  * NOTE that the file descriptor will not be closed when the
5463  *      reader is closed or reset.
5464  *
5465  * Returns the new reader or NULL in case of error.
5466  */
5467 xmlTextReaderPtr
5468 xmlReaderForFd(int fd, const char *URL, const char *encoding, int options)
5469 {
5470     xmlTextReaderPtr reader;
5471     xmlParserInputBufferPtr input;
5472
5473     if (fd < 0)
5474         return (NULL);
5475
5476     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5477     if (input == NULL)
5478         return (NULL);
5479     input->closecallback = NULL;
5480     reader = xmlNewTextReader(input, URL);
5481     if (reader == NULL) {
5482         xmlFreeParserInputBuffer(input);
5483         return (NULL);
5484     }
5485     reader->allocs |= XML_TEXTREADER_INPUT;
5486     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5487     return (reader);
5488 }
5489
5490 /**
5491  * xmlReaderForIO:
5492  * @ioread:  an I/O read function
5493  * @ioclose:  an I/O close function
5494  * @ioctx:  an I/O handler
5495  * @URL:  the base URL to use for the document
5496  * @encoding:  the document encoding, or NULL
5497  * @options:  a combination of xmlParserOption
5498  *
5499  * Create an xmltextReader for an XML document from I/O functions and source.
5500  * The parsing flags @options are a combination of xmlParserOption.
5501  *
5502  * Returns the new reader or NULL in case of error.
5503  */
5504 xmlTextReaderPtr
5505 xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
5506                void *ioctx, const char *URL, const char *encoding,
5507                int options)
5508 {
5509     xmlTextReaderPtr reader;
5510     xmlParserInputBufferPtr input;
5511
5512     if (ioread == NULL)
5513         return (NULL);
5514
5515     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5516                                          XML_CHAR_ENCODING_NONE);
5517     if (input == NULL) {
5518         if (ioclose != NULL)
5519             ioclose(ioctx);
5520         return (NULL);
5521     }
5522     reader = xmlNewTextReader(input, URL);
5523     if (reader == NULL) {
5524         xmlFreeParserInputBuffer(input);
5525         return (NULL);
5526     }
5527     reader->allocs |= XML_TEXTREADER_INPUT;
5528     xmlTextReaderSetup(reader, NULL, URL, encoding, options);
5529     return (reader);
5530 }
5531
5532 /**
5533  * xmlReaderNewWalker:
5534  * @reader:  an XML reader
5535  * @doc:  a preparsed document
5536  *
5537  * Setup an xmltextReader to parse a preparsed XML document.
5538  * This reuses the existing @reader xmlTextReader.
5539  *
5540  * Returns 0 in case of success and -1 in case of error
5541  */
5542 int
5543 xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc)
5544 {
5545     if (doc == NULL)
5546         return (-1);
5547     if (reader == NULL)
5548         return (-1);
5549
5550     if (reader->input != NULL) {
5551         xmlFreeParserInputBuffer(reader->input);
5552     }
5553     if (reader->ctxt != NULL) {
5554         xmlCtxtReset(reader->ctxt);
5555     }
5556
5557     reader->entNr = 0;
5558     reader->input = NULL;
5559     reader->mode = XML_TEXTREADER_MODE_INITIAL;
5560     reader->node = NULL;
5561     reader->curnode = NULL;
5562     reader->base = 0;
5563     reader->cur = 0;
5564     reader->allocs = XML_TEXTREADER_CTXT;
5565     reader->doc = doc;
5566     reader->state = XML_TEXTREADER_START;
5567     if (reader->dict == NULL) {
5568         if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL))
5569             reader->dict = reader->ctxt->dict;
5570         else
5571             reader->dict = xmlDictCreate();
5572     }
5573     return(0);
5574 }
5575
5576 /**
5577  * xmlReaderNewDoc:
5578  * @reader:  an XML reader
5579  * @cur:  a pointer to a zero terminated string
5580  * @URL:  the base URL to use for the document
5581  * @encoding:  the document encoding, or NULL
5582  * @options:  a combination of xmlParserOption
5583  *
5584  * Setup an xmltextReader to parse an XML in-memory document.
5585  * The parsing flags @options are a combination of xmlParserOption.
5586  * This reuses the existing @reader xmlTextReader.
5587  *
5588  * Returns 0 in case of success and -1 in case of error
5589  */
5590 int
5591 xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur,
5592                 const char *URL, const char *encoding, int options)
5593 {
5594
5595     int len;
5596
5597     if (cur == NULL)
5598         return (-1);
5599     if (reader == NULL)
5600         return (-1);
5601
5602     len = xmlStrlen(cur);
5603     return (xmlReaderNewMemory(reader, (const char *)cur, len,
5604                                URL, encoding, options));
5605 }
5606
5607 /**
5608  * xmlReaderNewFile:
5609  * @reader:  an XML reader
5610  * @filename:  a file or URL
5611  * @encoding:  the document encoding, or NULL
5612  * @options:  a combination of xmlParserOption
5613  *
5614  * parse an XML file from the filesystem or the network.
5615  * The parsing flags @options are a combination of xmlParserOption.
5616  * This reuses the existing @reader xmlTextReader.
5617  *
5618  * Returns 0 in case of success and -1 in case of error
5619  */
5620 int
5621 xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename,
5622                  const char *encoding, int options)
5623 {
5624     xmlParserInputBufferPtr input;
5625
5626     if (filename == NULL)
5627         return (-1);
5628     if (reader == NULL)
5629         return (-1);
5630
5631     input =
5632         xmlParserInputBufferCreateFilename(filename,
5633                                            XML_CHAR_ENCODING_NONE);
5634     if (input == NULL)
5635         return (-1);
5636     return (xmlTextReaderSetup(reader, input, filename, encoding, options));
5637 }
5638
5639 /**
5640  * xmlReaderNewMemory:
5641  * @reader:  an XML reader
5642  * @buffer:  a pointer to a char array
5643  * @size:  the size of the array
5644  * @URL:  the base URL to use for the document
5645  * @encoding:  the document encoding, or NULL
5646  * @options:  a combination of xmlParserOption
5647  *
5648  * Setup an xmltextReader to parse an XML in-memory document.
5649  * The parsing flags @options are a combination of xmlParserOption.
5650  * This reuses the existing @reader xmlTextReader.
5651  *
5652  * Returns 0 in case of success and -1 in case of error
5653  */
5654 int
5655 xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size,
5656                    const char *URL, const char *encoding, int options)
5657 {
5658     xmlParserInputBufferPtr input;
5659
5660     if (reader == NULL)
5661         return (-1);
5662     if (buffer == NULL)
5663         return (-1);
5664
5665     input = xmlParserInputBufferCreateStatic(buffer, size,
5666                                       XML_CHAR_ENCODING_NONE);
5667     if (input == NULL) {
5668         return (-1);
5669     }
5670     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5671 }
5672
5673 /**
5674  * xmlReaderNewFd:
5675  * @reader:  an XML reader
5676  * @fd:  an open file descriptor
5677  * @URL:  the base URL to use for the document
5678  * @encoding:  the document encoding, or NULL
5679  * @options:  a combination of xmlParserOption
5680  *
5681  * Setup an xmltextReader to parse an XML from a file descriptor.
5682  * NOTE that the file descriptor will not be closed when the
5683  *      reader is closed or reset.
5684  * The parsing flags @options are a combination of xmlParserOption.
5685  * This reuses the existing @reader xmlTextReader.
5686  *
5687  * Returns 0 in case of success and -1 in case of error
5688  */
5689 int
5690 xmlReaderNewFd(xmlTextReaderPtr reader, int fd,
5691                const char *URL, const char *encoding, int options)
5692 {
5693     xmlParserInputBufferPtr input;
5694
5695     if (fd < 0)
5696         return (-1);
5697     if (reader == NULL)
5698         return (-1);
5699
5700     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
5701     if (input == NULL)
5702         return (-1);
5703     input->closecallback = NULL;
5704     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5705 }
5706
5707 /**
5708  * xmlReaderNewIO:
5709  * @reader:  an XML reader
5710  * @ioread:  an I/O read function
5711  * @ioclose:  an I/O close function
5712  * @ioctx:  an I/O handler
5713  * @URL:  the base URL to use for the document
5714  * @encoding:  the document encoding, or NULL
5715  * @options:  a combination of xmlParserOption
5716  *
5717  * Setup an xmltextReader to parse an XML document from I/O functions
5718  * and source.
5719  * The parsing flags @options are a combination of xmlParserOption.
5720  * This reuses the existing @reader xmlTextReader.
5721  *
5722  * Returns 0 in case of success and -1 in case of error
5723  */
5724 int
5725 xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
5726                xmlInputCloseCallback ioclose, void *ioctx,
5727                const char *URL, const char *encoding, int options)
5728 {
5729     xmlParserInputBufferPtr input;
5730
5731     if (ioread == NULL)
5732         return (-1);
5733     if (reader == NULL)
5734         return (-1);
5735
5736     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
5737                                          XML_CHAR_ENCODING_NONE);
5738     if (input == NULL) {
5739         if (ioclose != NULL)
5740             ioclose(ioctx);
5741         return (-1);
5742     }
5743     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
5744 }
5745
5746 /************************************************************************
5747  *                                                                      *
5748  *                      Utilities                                       *
5749  *                                                                      *
5750  ************************************************************************/
5751 #ifdef NOT_USED_YET
5752
5753 /**
5754  * xmlBase64Decode:
5755  * @in:  the input buffer
5756  * @inlen:  the size of the input (in), the size read from it (out)
5757  * @to:  the output buffer
5758  * @tolen:  the size of the output (in), the size written to (out)
5759  *
5760  * Base64 decoder, reads from @in and save in @to
5761  * TODO: tell jody when this is actually exported
5762  *
5763  * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
5764  *         2 if there wasn't enough space on the output or -1 in case of error.
5765  */
5766 static int
5767 xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
5768                 unsigned char *to, unsigned long *tolen)
5769 {
5770     unsigned long incur;        /* current index in in[] */
5771
5772     unsigned long inblk;        /* last block index in in[] */
5773
5774     unsigned long outcur;       /* current index in out[] */
5775
5776     unsigned long inmax;        /* size of in[] */
5777
5778     unsigned long outmax;       /* size of out[] */
5779
5780     unsigned char cur;          /* the current value read from in[] */
5781
5782     unsigned char intmp[4], outtmp[4];  /* temporary buffers for the convert */
5783
5784     int nbintmp;                /* number of byte in intmp[] */
5785
5786     int is_ignore;              /* cur should be ignored */
5787
5788     int is_end = 0;             /* the end of the base64 was found */
5789
5790     int retval = 1;
5791
5792     int i;
5793
5794     if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
5795         return (-1);
5796
5797     incur = 0;
5798     inblk = 0;
5799     outcur = 0;
5800     inmax = *inlen;
5801     outmax = *tolen;
5802     nbintmp = 0;
5803
5804     while (1) {
5805         if (incur >= inmax)
5806             break;
5807         cur = in[incur++];
5808         is_ignore = 0;
5809         if ((cur >= 'A') && (cur <= 'Z'))
5810             cur = cur - 'A';
5811         else if ((cur >= 'a') && (cur <= 'z'))
5812             cur = cur - 'a' + 26;
5813         else if ((cur >= '0') && (cur <= '9'))
5814             cur = cur - '0' + 52;
5815         else if (cur == '+')
5816             cur = 62;
5817         else if (cur == '/')
5818             cur = 63;
5819         else if (cur == '.')
5820             cur = 0;
5821         else if (cur == '=')    /*no op , end of the base64 stream */
5822             is_end = 1;
5823         else {
5824             is_ignore = 1;
5825             if (nbintmp == 0)
5826                 inblk = incur;
5827         }
5828
5829         if (!is_ignore) {
5830             int nbouttmp = 3;
5831
5832             int is_break = 0;
5833
5834             if (is_end) {
5835                 if (nbintmp == 0)
5836                     break;
5837                 if ((nbintmp == 1) || (nbintmp == 2))
5838                     nbouttmp = 1;
5839                 else
5840                     nbouttmp = 2;
5841                 nbintmp = 3;
5842                 is_break = 1;
5843             }
5844             intmp[nbintmp++] = cur;
5845             /*
5846              * if intmp is full, push the 4byte sequence as a 3 byte
5847              * sequence out
5848              */
5849             if (nbintmp == 4) {
5850                 nbintmp = 0;
5851                 outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
5852                 outtmp[1] =
5853                     ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
5854                 outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
5855                 if (outcur + 3 >= outmax) {
5856                     retval = 2;
5857                     break;
5858                 }
5859
5860                 for (i = 0; i < nbouttmp; i++)
5861                     to[outcur++] = outtmp[i];
5862                 inblk = incur;
5863             }
5864
5865             if (is_break) {
5866                 retval = 0;
5867                 break;
5868             }
5869         }
5870     }
5871
5872     *tolen = outcur;
5873     *inlen = inblk;
5874     return (retval);
5875 }
5876
5877 /*
5878  * Test routine for the xmlBase64Decode function
5879  */
5880 #if 0
5881 int
5882 main(int argc, char **argv)
5883 {
5884     char *input = "  VW4 gcGV0        \n      aXQgdGVzdCAuCg== ";
5885
5886     char output[100];
5887
5888     char output2[100];
5889
5890     char output3[100];
5891
5892     unsigned long inlen = strlen(input);
5893
5894     unsigned long outlen = 100;
5895
5896     int ret;
5897
5898     unsigned long cons, tmp, tmp2, prod;
5899
5900     /*
5901      * Direct
5902      */
5903     ret = xmlBase64Decode(input, &inlen, output, &outlen);
5904
5905     output[outlen] = 0;
5906     printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen,
5907            outlen, output)indent: Standard input:179: Error:Unmatched #endif
5908 ;
5909
5910     /*
5911      * output chunking
5912      */
5913     cons = 0;
5914     prod = 0;
5915     while (cons < inlen) {
5916         tmp = 5;
5917         tmp2 = inlen - cons;
5918
5919         printf("%ld %ld\n", cons, prod);
5920         ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
5921         cons += tmp2;
5922         prod += tmp;
5923         printf("%ld %ld\n", cons, prod);
5924     }
5925     output2[outlen] = 0;
5926     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5927            prod, output2);
5928
5929     /*
5930      * input chunking
5931      */
5932     cons = 0;
5933     prod = 0;
5934     while (cons < inlen) {
5935         tmp = 100 - prod;
5936         tmp2 = inlen - cons;
5937         if (tmp2 > 5)
5938             tmp2 = 5;
5939
5940         printf("%ld %ld\n", cons, prod);
5941         ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
5942         cons += tmp2;
5943         prod += tmp;
5944         printf("%ld %ld\n", cons, prod);
5945     }
5946     output3[outlen] = 0;
5947     printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons,
5948            prod, output3);
5949     return (0);
5950
5951 }
5952 #endif
5953 #endif /* NOT_USED_YET */
5954 #define bottom_xmlreader
5955 #include "elfgcchack.h"
5956 #endif /* LIBXML_READER_ENABLED */