File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / xmlreader.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:29 2014 UTC (10 years ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

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

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