pattern.c revision 38ae7e4efe803ea78b6499cd05a394db32623e41
/*
* pattern.c: Implemetation of selectors for nodes
*
* Reference:
* to some extent
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
*/
/*
* TODO:
* - compilation flags to check for specific syntaxes
* using flags of xmlPatterncompile()
* - making clear how pattern starting with / or . need to be handled,
* currently push(NULL, NULL) means a reset of the streaming context
* and indicating we are on / (the document node), probably need
* something similar for .
* - get rid of the "compile" starting with lowercase
*/
#define IN_LIBXML
#include "libxml.h"
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlerror.h>
#include <libxml/parserInternals.h>
#ifdef LIBXML_PATTERN_ENABLED
/* #define DEBUG_STREAMING */
#define ERROR(a, b, c, d)
#define ERROR5(a, b, c, d, e)
#define XML_STREAM_STEP_DESC 1
#define XML_STREAM_STEP_FINAL 2
#define XML_STREAM_STEP_ROOT 4
#define XML_STREAM_STEP_ATTR 8
#define XML_STREAM_STEP_NODE 16
#define XML_STREAM_STEP_IN_SET 32
/*
* NOTE: Those private flags (XML_STREAM_xxx) are used
* in _xmlStreamCtxt->flag. They extend the public
* xmlPatternFlags, so be carefull not to interfere with the
* reserved values for xmlPatternFlags.
*/
/*
* XML_STREAM_ANY_NODE is used for comparison against
* xmlElementType enums, to indicate a node of any type.
*/
#define XML_STREAM_ANY_NODE 100
#define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \
#define XML_STREAM_XS_IDC(c) ((c)->flags & \
#define XML_PAT_COPY_NSNAME(c, r, nsname) \
typedef struct _xmlStreamStep xmlStreamStep;
typedef xmlStreamStep *xmlStreamStepPtr;
struct _xmlStreamStep {
int flags; /* properties of that step */
int nodeType; /* type of node */
};
typedef struct _xmlStreamComp xmlStreamComp;
typedef xmlStreamComp *xmlStreamCompPtr;
struct _xmlStreamComp {
int nbStep; /* number of steps in the automata */
int maxStep; /* allocated number of steps */
int flags;
};
struct _xmlStreamCtxt {
int nbState; /* number of states in the automata */
int maxState; /* allocated number of states */
int level; /* how deep are we ? */
int *states; /* the array of step indexes */
int flags; /* validation options */
int blockLevel;
};
/*
* Types are private:
*/
typedef enum {
XML_OP_END=0,
} xmlPatOp;
typedef struct _xmlStepState xmlStepState;
typedef xmlStepState *xmlStepStatePtr;
struct _xmlStepState {
int step;
};
typedef struct _xmlStepStates xmlStepStates;
typedef xmlStepStates *xmlStepStatesPtr;
struct _xmlStepStates {
int nbstates;
int maxstates;
};
typedef struct _xmlStepOp xmlStepOp;
typedef xmlStepOp *xmlStepOpPtr;
struct _xmlStepOp {
};
struct _xmlPattern {
void *data; /* the associated template */
int flags; /* flags */
int nbStep;
int maxStep;
};
typedef struct _xmlPatParserContext xmlPatParserContext;
typedef xmlPatParserContext *xmlPatParserContextPtr;
struct _xmlPatParserContext {
int error; /* error code */
int nb_namespaces; /* the number of namespaces */
};
/************************************************************************
* *
* Type functions *
* *
************************************************************************/
/**
* xmlNewPattern:
*
* Create a new XSLT Pattern
*
* Returns the newly allocated xmlPatternPtr or NULL in case of error
*/
static xmlPatternPtr
xmlNewPattern(void) {
"xmlNewPattern : malloc failed\n");
return(NULL);
}
"xmlNewPattern : malloc failed\n");
return(NULL);
}
return(cur);
}
/**
* xmlFreePattern:
* @comp: an XSLT comp
*
* Free up the memory allocated by @comp
*/
void
int i;
return;
}
}
}
}
/**
* xmlFreePatternList:
* @comp: an XSLT comp list
*
* Free up the memory allocated by all the elements of @comp
*/
void
}
}
/**
* xmlNewPatParserContext:
* @pattern: the pattern context
* @dict: the inherited dictionary or NULL
* @namespaces: the prefix definitions, array of [URI, prefix] terminated
* with [NULL, NULL] or NULL if no namespace is used
*
* Create a new XML pattern parser context
*
* Returns the newly allocated xmlPatParserContextPtr or NULL in case of error
*/
static xmlPatParserContextPtr
const xmlChar **namespaces) {
return(NULL);
"xmlNewPatParserContext : malloc failed\n");
return(NULL);
}
if (namespaces != NULL) {
int i;
cur->nb_namespaces = i;
} else {
cur->nb_namespaces = 0;
}
return(cur);
}
/**
* xmlFreePatParserContext:
* @ctxt: an XSLT parser context
*
* Free up the memory allocated by @ctxt
*/
static void
return;
}
/**
* xmlPatternAdd:
* @comp: the compiled match expression
* @op: an op
* @value: the first value
* @value2: the second value
*
* Add a step to an XSLT Compiled Match
*
* Returns -1 in case of failure, 0 otherwise.
*/
static int
{
sizeof(xmlStepOp));
"xmlPatternAdd: realloc failed\n");
return (-1);
}
}
return (0);
}
#if 0
/**
* xsltSwapTopPattern:
* @comp: the compiled match expression
*
* reverse the two top steps.
*/
static void
int i;
if (j > 0) {
i = j - 1;
}
}
#endif
/**
* xmlReversePattern:
* @comp: the compiled match expression
*
* reverse all the stack of expressions
*
* returns 0 in case of success and -1 in case of error.
*/
static int
int i, j;
/*
* remove the leading // for //a or .//a
*/
}
}
sizeof(xmlStepOp));
"xmlReversePattern: realloc failed\n");
return (-1);
}
}
i = 0;
while (j > i) {
j--;
i++;
}
return(0);
}
/************************************************************************
* *
* The interpreter for the precompiled patterns *
* *
************************************************************************/
static int
}
return(-1);
}
#if 0
#endif
return(0);
}
/**
* xmlPatMatch:
* @comp: the precompiled pattern
* @node: a node
*
* Test whether the node matches the pattern
*
* Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
*/
static int
int i;
i = 0;
case XML_OP_END:
goto found;
case XML_OP_ROOT:
goto rollback;
#ifdef LIBXML_DOCB_ENABLED
#endif
continue;
goto rollback;
case XML_OP_ELEM:
goto rollback;
continue;
goto rollback;
goto rollback;
/* Namespace test */
goto rollback;
goto rollback;
goto rollback;
}
continue;
case XML_OP_CHILD: {
#ifdef LIBXML_DOCB_ENABLED
#endif
goto rollback;
break;
}
continue;
}
goto rollback;
}
case XML_OP_ATTR:
goto rollback;
goto rollback;
goto rollback;
}
/* Namespace test */
goto rollback;
goto rollback;
}
continue;
case XML_OP_PARENT:
#ifdef LIBXML_DOCB_ENABLED
#endif
goto rollback;
goto rollback;
continue;
goto rollback;
goto rollback;
/* Namespace test */
goto rollback;
goto rollback;
goto rollback;
}
continue;
case XML_OP_ANCESTOR:
i++;
goto found;
goto rollback;
return(-1);
}
goto rollback;
#ifdef LIBXML_DOCB_ENABLED
#endif
goto rollback;
/* Namespace test */
break;
break;
}
}
}
goto rollback;
/*
* prepare a potential rollback from here
* for ancestors of that node.
*/
else
continue;
case XML_OP_NS:
goto rollback;
goto rollback;
goto rollback;
goto rollback;
}
break;
case XML_OP_ALL:
goto rollback;
break;
}
}
/* Free the rollback states */
}
return(1);
/* got an error try to rollback */
return(0);
return(0);
}
#if 0
#endif
goto restart;
}
/************************************************************************
* *
* Dedicated parser for templates *
* *
************************************************************************/
#define TODO \
"Unimplemented block at %s:%d\n", \
#define SKIP_BLANKS \
#define XSLT_ERROR(X) \
#define XSLT_ERROR0(X) \
#if 0
/**
* xmlPatScanLiteral:
* @ctxt: the XPath Parser context
*
* Parse an XPath Litteral:
*
* [29] Literal ::= '"' [^"]* '"'
* | "'" [^']* "'"
*
* Returns the Literal parsed or NULL
*/
static xmlChar *
if (CUR == '"') {
NEXT;
}
return(NULL);
} else {
else
}
} else if (CUR == '\'') {
NEXT;
}
return(NULL);
} else {
else
}
} else {
/* XP_ERROR(XPATH_START_LITERAL_ERROR); */
return(NULL);
}
return(ret);
}
#endif
/**
* xmlPatScanName:
* @ctxt: the XPath Parser context
*
* [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
* CombiningChar | Extender
*
* [5] Name ::= (Letter | '_' | ':') (NameChar)*
*
* [6] Names ::= Name (S Name)*
*
* Returns the Name parsed or NULL
*/
static xmlChar *
return(NULL);
(val == '_') ||
(IS_COMBINING(val)) ||
(IS_EXTENDER(val))) {
}
else
return(ret);
}
/**
* xmlPatScanNCName:
* @ctxt: the XPath Parser context
*
* Parses a non qualified name
*
* Returns the Name parsed or NULL
*/
static xmlChar *
return(NULL);
(val == '_') ||
(IS_COMBINING(val)) ||
(IS_EXTENDER(val))) {
}
else
return(ret);
}
#if 0
/**
* xmlPatScanQName:
* @ctxt: the XPath Parser context
* @prefix: the place to store the prefix
*
* Parse a qualified name
*
* Returns the Name parsed or NULL
*/
static xmlChar *
if (CUR == ':') {
NEXT;
}
return(ret);
}
#endif
/**
* xmlCompileAttributeTest:
* @ctxt: the compilation context
*
* Compile an attribute test.
*/
static void
if (CUR == '*') {
NEXT;
} else {
"xmlCompileAttributeTest : Name expected\n");
}
return;
}
if (CUR == ':') {
int i;
NEXT;
if (IS_BLANK_CH(CUR)) {
goto error;
}
/*
* This is a namespace match
*/
if ((prefix[0] == 'x') &&
(prefix[3] == 0))
{
} else {
for (i = 0;i < ctxt->nb_namespaces;i++) {
break;
}
}
if (i >= ctxt->nb_namespaces) {
"xmlCompileAttributeTest : no namespace bound to prefix %s\n",
prefix);
goto error;
}
}
if (CUR == '*') {
NEXT;
} else {
"xmlCompileAttributeTest : Name expected\n");
goto error;
}
} else {
}
} else {
}
return;
}
/**
* xmlCompileStepPattern:
* @ctxt: the compilation context
*
* Compile the Step Pattern and generates a precompiled
* form suitable for fast matching.
*
* [3] Step ::= '.' | NameTest
* [4] NameTest ::= QName | '*' | NCName ':' '*'
*/
static void
int hasBlanks = 0;
if (CUR == '.') {
/*
* Context node.
*/
NEXT;
return;
}
if (CUR == '@') {
/*
* Attribute test.
*/
return;
}
NEXT;
goto error;
return;
}
if (CUR == '*') {
NEXT;
return;
} else {
"xmlCompileStepPattern : Name expected\n");
return;
}
}
if (IS_BLANK_CH(CUR)) {
hasBlanks = 1;
}
if (CUR == ':') {
NEXT;
if (CUR != ':') {
int i;
goto error;
}
/*
* This is a namespace match
*/
if ((prefix[0] == 'x') &&
(prefix[3] == 0))
{
} else {
for (i = 0;i < ctxt->nb_namespaces;i++) {
break;
}
}
if (i >= ctxt->nb_namespaces) {
"xmlCompileStepPattern : no namespace bound to prefix %s\n",
prefix);
goto error;
}
}
if (CUR == '*') {
NEXT;
} else {
"xmlCompileStepPattern : Name expected\n");
goto error;
}
} else {
}
} else {
NEXT;
if (CUR == '*') {
NEXT;
return;
} else {
"xmlCompileStepPattern : QName expected\n");
goto error;
}
}
if (CUR == ':') {
int i;
NEXT;
if (IS_BLANK_CH(CUR)) {
goto error;
}
/*
* This is a namespace match
*/
if ((prefix[0] == 'x') &&
(prefix[3] == 0))
{
} else {
for (i = 0;i < ctxt->nb_namespaces;i++) {
break;
}
}
if (i >= ctxt->nb_namespaces) {
"xmlCompileStepPattern : no namespace bound "
"to prefix %s\n", prefix);
goto error;
}
}
if (CUR == '*') {
NEXT;
} else {
"xmlCompileStepPattern : Name expected\n");
goto error;
}
} else {
}
} else
return;
goto error;
}
goto error;
return;
} else {
"The 'element' or 'attribute' axis is expected.\n", NULL);
goto error;
}
}
} else if (CUR == '*') {
goto error;
}
NEXT;
} else {
}
return;
}
/**
* xmlCompilePathPattern:
* @ctxt: the compilation context
*
* Compile the Path Pattern and generates a precompiled
* form suitable for fast matching.
*
* [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
*/
static void
if (CUR == '/') {
}
NEXT;
NEXT;
NEXT;
NEXT;
NEXT;
/* Check for incompleteness. */
if (CUR == 0) {
goto error;
}
}
if (CUR == '@') {
NEXT;
/* TODO: check for incompleteness */
if (CUR != 0) {
goto error;
}
} else {
if (CUR == '/') {
NEXT;
/* Check for incompleteness. */
if (CUR == 0) {
goto error;
}
}
goto error;
while (CUR == '/') {
NEXT;
NEXT;
goto error;
} else {
NEXT;
if (CUR == 0) {
goto error;
}
goto error;
}
}
}
if (CUR != 0) {
}
return;
}
/**
* xmlCompileIDCXPathPath:
* @ctxt: the compilation context
*
* Compile the Path Pattern and generates a precompiled
* form suitable for fast matching.
*
* [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
*/
static void
if (CUR == '/') {
"Unexpected selection of the document root in '%s'.\n",
goto error;
}
if (CUR == '.') {
/* "." - "self::node()" */
NEXT;
if (CUR == 0) {
/*
* Selection of the context node.
*/
return;
}
if (CUR != '/') {
/* TODO: A more meaningful error message. */
goto error;
}
/* "./" - "self::node()/" */
NEXT;
if (CUR == '/') {
/*
* Disallow "./ /"
*/
goto error;
}
/* ".//" - "self:node()/descendant-or-self::node()/" */
NEXT;
}
if (CUR == 0)
goto error_unfinished;
}
/*
* Process steps.
*/
do {
goto error;
if (CUR != '/')
break;
NEXT;
if (CUR == '/') {
/*
* Disallow subsequent '//'.
*/
"Unexpected subsequent '//' in '%s'.\n",
goto error;
}
if (CUR == 0)
goto error_unfinished;
} while (CUR != 0);
if (CUR != 0) {
}
return;
return;
return;
}
/************************************************************************
* *
* The streaming code *
* *
************************************************************************/
#ifdef DEBUG_STREAMING
static void
int i;
printf("Stream: NULL\n");
return;
}
}
printf("* ");
} else {
}
printf("root ");
printf("// ");
printf("final ");
printf("\n");
}
}
static void
int i;
printf("Stream: NULL\n");
return;
}
if (match)
printf("matches\n");
else
printf("\n");
printf(" %d: free\n", i);
else {
printf(" //\n");
else
printf("\n");
}
}
}
#endif
/**
* xmlNewStreamComp:
* @size: the number of expected steps
*
* build a new compiled pattern for streaming
*
* Returns the new structure or NULL in case of error.
*/
static xmlStreamCompPtr
xmlNewStreamComp(int size) {
if (size < 4)
size = 4;
"xmlNewStreamComp: malloc failed\n");
return(NULL);
}
"xmlNewStreamComp: malloc failed\n");
return(NULL);
}
return(cur);
}
/**
* xmlFreeStreamComp:
* @comp: the compiled pattern for streaming
*
* Free the compiled pattern for streaming
*/
static void
}
}
/**
* xmlStreamCompAddStep:
* @comp: the compiled pattern for streaming
* @name: the first string, the name, or NULL for *
* @ns: the second step, the namespace name
* @flags: the flags for that step
*
* Add a new step to the compiled pattern
*
* Returns -1 in case of error or the step index if successful
*/
static int
"xmlNewStreamComp: malloc failed\n");
return(-1);
}
}
}
/**
* xmlStreamCompile:
* @comp: the precompiled pattern
*
* Tries to stream compile a pattern
*
* Returns -1 in case of failure and 0 in case of success.
*/
static int
return(-1);
/*
* special case for .
*/
stream = xmlNewStreamComp(0);
return(-1);
/* Note that the stream will have no steps in this case. */
return(0);
}
return(-1);
}
i = 0;
case XML_OP_END:
break;
case XML_OP_ROOT:
if (i != 0)
goto error;
root = 1;
break;
case XML_OP_NS:
if (s < 0)
goto error;
prevs = s;
flags = 0;
break;
case XML_OP_ATTR:
prevs = -1;
flags = 0;
if (s < 0)
goto error;
break;
case XML_OP_ELEM:
/*
* We have a "." or "self::node()" here.
* Eliminate redundant self::node() tests like in "/./."
* or "//./"
* The only case we won't eliminate is "//.", i.e. if
* self::node() is the last node test and we had
* continuation somewhere beforehand.
*/
(flags & XML_STREAM_STEP_DESC)) {
/*
* Mark the special case where the expression resolves
* to any type of node.
*/
}
if (s < 0)
goto error;
flags = 0;
/*
* If there was a previous step, mark it to be added to
* the result node-set; this is needed since only
* the last step will be marked as "final" and only
* "final" nodes are added to the resulting set.
*/
if (prevs != -1) {
prevs = -1;
}
break;
} else {
/* Just skip this one. */
continue;
}
}
/* An element node. */
if (s < 0)
goto error;
prevs = s;
flags = 0;
break;
case XML_OP_CHILD:
/* An element node child. */
if (s < 0)
goto error;
prevs = s;
flags = 0;
break;
case XML_OP_ALL:
if (s < 0)
goto error;
prevs = s;
flags = 0;
break;
case XML_OP_PARENT:
break;
case XML_OP_ANCESTOR:
/* Skip redundant continuations. */
if (flags & XML_STREAM_STEP_DESC)
break;
/*
* Mark the expression as having "//".
*/
break;
}
}
/*
* If this should behave like a real pattern, we will mark
* the first step as having "//", to be reentrant on every
* tree level.
*/
}
}
goto error;
if (root)
#ifdef DEBUG_STREAMING
#endif
return(0);
return(0);
}
/**
* xmlNewStreamCtxt:
* @size: the number of expected states
*
* build a new stream context
*
* Returns the new structure or NULL in case of error.
*/
static xmlStreamCtxtPtr
"xmlNewStreamCtxt: malloc failed\n");
return(NULL);
}
"xmlNewStreamCtxt: malloc failed\n");
return(NULL);
}
return(cur);
}
/**
* xmlFreeStreamCtxt:
* @stream: the stream context
*
* Free the stream context
*/
void
}
}
/**
* xmlStreamCtxtAddState:
* @comp: the stream context
* @idx: the step index for that streaming state
*
* Add a new state to the stream context
*
* Returns -1 in case of error or the state index if successful
*/
static int
int i;
return(i);
}
}
int *cur;
"xmlNewStreamCtxt: malloc failed\n");
return(-1);
}
}
}
/**
* xmlStreamPushInternal:
* @stream: the stream context
* @name: the current name
* @ns: the namespace name
* @nodeType: the type of the node
*
* Push new data onto the stream. NOTE: if the call xmlPatterncompile()
* indicated a dictionary, then strings for name and ns will be expected
* to come from the dictionary.
* Both @name and @ns being NULL means the / i.e. the root of the document.
* This can also act as a reset.
*
* Returns: -1 in case of error, 1 if the current state in the stream is a
* match and 0 otherwise.
*/
static int
int nodeType) {
#ifdef DEBUG_STREAMING
#endif
return(-1);
if ((nodeType == XML_ELEMENT_NODE) &&
/* We have a document node here (or a reset). */
/* TODO: We have a "/." here? */
ret = 1;
} else {
{
/*
* In the case of "//." the document node will match
* as well.
*/
ret = 1;
/* TODO: Do we need this ? */
if (tmp < 0)
err++;
}
}
}
continue; /* while */
}
/*
* Fast check for ".".
*/
/*
* / and . are handled at the XPath node set creation
* level by checking min depth
*/
continue; /* while */
}
/*
* For non-pattern like evaluation like XML Schema IDCs
* or traditional XPath expressions, this will match if
* we are at the first level only, otherwise on every level.
*/
if ((nodeType != XML_ATTRIBUTE_NODE) &&
ret = 1;
}
goto stream_next;
}
/*
* Skip blocked expressions.
*/
goto stream_next;
}
if ((nodeType != XML_ELEMENT_NODE) &&
(nodeType != XML_ATTRIBUTE_NODE) &&
/*
* No need to process nodes of other types if we don't
* resolve to those types.
* TODO: Do we need to block the context here?
*/
goto stream_next;
}
/*
* Check evolution of existing states
*/
i = 0;
while (i < m) {
/*
* If there is no "//", then only the last
* added state is of interest.
*/
/*
* TODO: Security check, should not happen, remove it.
*/
return (-1);
}
desc = 0;
/* loop-stopper */
i = m;
} else {
/*
* If there are "//", then we need to process every "//"
* occuring in the states, plus any other state for this
* level.
*/
/* TODO: should not happen anymore: dead states */
if (stepNr < 0)
goto next_state;
/* skip new states just added */
goto next_state;
/* skip states at ancestor levels, except if "//" */
goto next_state;
}
/*
* Check for correct node-type.
*/
/*
* Block this expression for deeper evaluation.
*/
goto next_state;
goto next_state;
}
/*
* Compare local/namespace-name.
*/
match = 0;
match = 1;
/*
* This lets through all elements/attributes.
*/
match = 1;
{
match = 1;
}
#if 0
/*
* TODO: Pointer comparison won't work, since not guaranteed that the given
* values are in the same dict; especially if it's the namespace name,
* normally coming from ns->href. We need a namespace dict mechanism !
*/
match = 1;
else
} else {
}
#endif /* if 0 ------------------------------------------------------- */
if (match) {
if (desc) {
if (final) {
ret = 1;
} else {
/* descending match create a new state */
}
} else {
if (final) {
ret = 1;
} else {
}
}
/*
* "foo" is selected as well.
*/
ret = 1;
}
}
/*
* Mark this expression as blocked for any evaluation at
* deeper levels. Note that this includes "/foo"
* expressions if the *pattern* behaviour is used.
*/
}
i++;
}
/*
* Don't reenter if it's an absolute expression like "/foo",
* except "//foo".
*/
goto stream_next;
/*
* or if we are at the 1st level of evaluation.
*/
if (XML_STREAM_XS_IDC(stream)) {
/*
* XS-IDC: The missing "self::node()" will always
* match the first given node.
*/
goto stream_next;
} else
goto compare;
}
/*
* A "//" is always reentrant.
*/
if (desc)
goto compare;
/*
* XS-IDC: Process the 2nd level, since the missing
* "self::node()" is responsible for the 2nd level being
* the real start level.
*/
goto compare;
goto stream_next;
}
/*
* Check expected node-type.
*/
if (nodeType == XML_ATTRIBUTE_NODE)
goto stream_next;
goto stream_next;
}
/*
* Compare local/namespace-name.
*/
match = 0;
match = 1;
/*
* This lets through all elements/attributes.
*/
match = 1;
{
match = 1;
}
if (match) {
if (final)
ret = 1;
else
/*
* Check if we have a special case like "foo//.", where
* "foo" is selected as well.
*/
ret = 1;
}
}
/*
* Mark this expression as blocked for any evaluation at
* deeper levels.
*/
}
} /* while stream != NULL */
if (err > 0)
ret = -1;
#ifdef DEBUG_STREAMING
#endif
return(ret);
}
/**
* xmlStreamPush:
* @stream: the stream context
* @name: the current name
* @ns: the namespace name
*
* Push new data onto the stream. NOTE: if the call xmlPatterncompile()
* indicated a dictionary, then strings for name and ns will be expected
* to come from the dictionary.
* Both @name and @ns being NULL means the / i.e. the root of the document.
* This can also act as a reset.
* Otherwise the function will act as if it has been given an element-node.
*
* Returns: -1 in case of error, 1 if the current state in the stream is a
* match and 0 otherwise.
*/
int
}
/**
* xmlStreamPushNode:
* @stream: the stream context
* @name: the current name
* @ns: the namespace name
* @nodeType: the type of the node being pushed
*
* Push new data onto the stream. NOTE: if the call xmlPatterncompile()
* indicated a dictionary, then strings for name and ns will be expected
* to come from the dictionary.
* Both @name and @ns being NULL means the / i.e. the root of the document.
* This can also act as a reset.
* Different from xmlStreamPush() this function can be fed with nodes of type:
* element-, attribute-, text-, cdata-section-, comment- and
* processing-instruction-node.
*
* Returns: -1 in case of error, 1 if the current state in the stream is a
* match and 0 otherwise.
*/
int
int nodeType)
{
nodeType));
}
/**
* xmlStreamPushAttr:
* @stream: the stream context
* @name: the current name
* @ns: the namespace name
*
* Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()
* indicated a dictionary, then strings for name and ns will be expected
* to come from the dictionary.
* Both @name and @ns being NULL means the / i.e. the root of the document.
* This can also act as a reset.
* Otherwise the function will act as if it has been given an attribute-node.
*
* Returns: -1 in case of error, 1 if the current state in the stream is a
* match and 0 otherwise.
*/
int
}
/**
* xmlStreamPop:
* @stream: the stream context
*
* push one level from the stream.
*
* Returns: -1 in case of error, 0 otherwise.
*/
int
int i, lev;
return(-1);
/*
* Reset block-level.
*/
return(-1);
/*
* Check evolution of existing states
*/
/* discard obsoleted states */
break;
}
}
return(0);
}
/**
* xmlStreamWantsAnyNode:
* @streamCtxt: the stream context
*
* Query if the streaming pattern additionally needs to be fed with
* text-, cdata-section-, comment- and processing-instruction-nodes.
* If the result is 0 then only element-nodes and attribute-nodes
* need to be pushed.
*
* Returns: 1 in case of need of nodes of the above described types,
* 0 otherwise. -1 on API errors.
*/
int
{
if (streamCtxt == NULL)
return(-1);
while (streamCtxt != NULL) {
return(1);
}
return(0);
}
/************************************************************************
* *
* The public interfaces *
* *
************************************************************************/
/**
* xmlPatterncompile:
* @pattern: the pattern to compile
* @dict: an optional dictionary for interned strings
* @flags: compilation flags, see xmlPatternFlags
* @namespaces: the prefix definitions, array of [URI, prefix] or NULL
*
* Compile a pattern.
*
* Returns the compiled form of the pattern or NULL in case of error
*/
const xmlChar **namespaces) {
int type = 0;
int streamable = 1;
return(NULL);
while (*or != 0) {
if (*or == 0)
else {
}
or++;
}
cur = xmlNewPattern();
/*
* Assign string dict.
*/
if (dict) {
}
else {
}
if (XML_STREAM_XS_IDC(cur))
else
goto error;
if (streamable) {
if (type == 0) {
} else if (type == PAT_FROM_ROOT) {
streamable = 0;
} else if (type == PAT_FROM_CUR) {
streamable = 0;
}
}
if (streamable)
if (xmlReversePattern(cur) < 0)
goto error;
}
}
if (streamable == 0) {
}
}
}
return(ret);
return(NULL);
}
/**
* xmlPatternMatch:
* @comp: the precompiled pattern
* @node: a node
*
* Test whether the node matches the pattern
*
* Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
*/
int
{
int ret = 0;
return(-1);
if (ret != 0)
return(ret);
}
return(ret);
}
/**
* xmlPatternGetStreamCtxt:
* @comp: the precompiled pattern
*
* Get a streaming context for that pattern
* Use xmlFreeStreamCtxt to free the context.
*
* Returns a pointer to the context or NULL in case of failure
*/
{
return(NULL);
goto failed;
goto failed;
else {
}
}
return(ret);
return(NULL);
}
/**
* xmlPatternStreamable:
* @comp: the precompiled pattern
*
* Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt()
* should work.
*
* Returns 1 if streamable, 0 if not and -1 in case of error.
*/
int
return(-1);
return(0);
}
return(1);
}
/**
* xmlPatternMaxDepth:
* @comp: the precompiled pattern
*
* Check the maximum depth reachable by a pattern
*
* Returns -2 if no limit (using //), otherwise the depth,
* and -1 in case of error
*/
int
int ret = 0, i;
return(-1);
return(-1);
return(-2);
}
return(ret);
}
/**
* xmlPatternMinDepth:
* @comp: the precompiled pattern
*
* Check the minimum depth reachable by a pattern, 0 mean the / or . are
* part of the set.
*
* Returns -1 in case of error otherwise the depth,
*
*/
int
int ret = 12345678;
return(-1);
return(-1);
if (ret == 0)
return(0);
}
return(ret);
}
/**
* xmlPatternFromRoot:
* @comp: the precompiled pattern
*
* Check if the pattern must be looked at from the root.
*
* Returns 1 if true, 0 if false and -1 in case of error
*/
int
return(-1);
return(-1);
return(1);
}
return(0);
}
#define bottom_pattern
#include "elfgcchack.h"
#endif /* LIBXML_PATTERN_ENABLED */