File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / xmlreader.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:22:22 2013 UTC (10 years, 11 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_8_0p0, v2_8_0, HEAD
2.8.0

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

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