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