📄 xpathpredicate.cpp
字号:
//**************************************************************************************************************************
//* Blue Xml Extension
//* Copyright (c) 2002-2004 Josh Harler
//*
//* Blue - General Purpose C++ Library
//* Copyright (c) 2002-2004 Josh Harler
//*
//* This software is provided 'as-is', without any express or implied warranty. In no event
//* will the authors be held liable for any damages arising from the use of this software.
//*
//* Permission is granted to anyone to use this software for any purpose, including commercial
//* applications, and to alter it and redistribute it freely, subject to the following restrictions:
//*
//* 1. The origin of this software must not be misrepresented; you must not claim that you
//* wrote the original software. If you use this software in a product, an acknowledgment in the
//* product documentation would be appreciated but is not required.
//*
//* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
//* being the original software.
//*
//* 3. This notice may not be removed or altered from any source distribution.
//*
//*
//* file Blue/Extension/Xml/XPathPredicate.cpp
//**
// Private Headers =========================================================================================================
// matching header
#include "XPathPredicate.h"
// Blue library headers
#include "Blue/Util/StringTokenizer.h"
// Extension headers
#include "XPathFunctions.h"
// Private Defines/Enums/Typedefs/Etc ======================================================================================
using namespace blue;
using namespace blue::common;
using namespace blue::util;
using namespace blue::ext;
using namespace blue::ext::xml;
// Private Classes/Structs =================================================================================================
// Private Global Variables ================================================================================================
// External Global Variables ===============================================================================================
// Private Functions =======================================================================================================
namespace {
inline bool priv_isOperator( String op )
{
return(
op == "=" || op == "!=" || op == "<" ||
op == "<=" || op == ">" || op == ">=" ||
op == "+" || op == "-" || op == "*" ||
op == "div" || op == "mult" || op == "mod" ||
op == "or" || op == "and" || op == ","
);
}
void priv_parseCheckMinus( Array<String>& tokens )
{
int iT = 1;
while( iT < tokens.getSize() - 1 ) {
if( tokens[iT] == "-" ) {
if( tokens[iT-1] != " " ) {
tokens[iT-1] += tokens[iT];
if( tokens[iT+1].trim().getLength() > 0 ) {
tokens[iT-1] += tokens[iT+1];
tokens.remove(iT+1);
}
tokens.remove(iT);
continue;
}
}
++iT;
}
}
void priv_parseRemoveWhitespace( Array<String>& tokens )
{
int iT = 0;
while( iT < tokens.getSize() ) {
if( tokens[iT].trim().getLength() == 0 ) {
tokens.remove(iT);
continue;
}
++iT;
}
}
void priv_parseConcatOperators( Array<String>& tokens )
{
int iT = 0;
while( iT < tokens.getSize() ) {
if( tokens[iT].getLength() == 1 ) {
switch(tokens[iT][0])
{
case '<': case '>': case '!':
if( iT < tokens.getSize() - 1 && tokens[iT+1] == "=" ) {
tokens[iT] += "=";
tokens.remove(iT+1);
}
break;
case '*':
if( iT > 0 ) {
String token = tokens[iT-1];
if( !priv_isOperator(token) && !token.isValidDouble() && token != "(" ) {
tokens[iT-1] += "*";
tokens.remove(iT);
continue;
}
}
break;
}
}
++iT;
}
}
void priv_parseConcatNonOperators( Array<String>& tokens )
{
int iT = 1;
bool lastOpParen = false;
while( iT < tokens.getSize() - 1 ) {
bool op = priv_isOperator(tokens[iT]);
bool paren = (op ? false : (tokens[iT] == "(" || tokens[iT] == ")"));
if( op || paren ) {
lastOpParen = true;
}
else {
if( !lastOpParen ) {
tokens[iT-1] += tokens[iT];
tokens.remove(iT);
continue;
}
lastOpParen = false;
}
++iT;
}
}
void priv_checkForNotFunctions( Array<String>& tokens, XPathPredicate& predicate )
{
int iT = 1;
while( iT < tokens.getSize() - 2 ) {
if( tokens[iT] == "(" && tokens[iT+1] == ")" ) {
if( !predicate.hasFunction(tokens[iT-1]) ) {
tokens[iT-1] += "()";
tokens.remove(iT+1);
tokens.remove(iT);
continue;
}
}
++iT;
}
}
int priv_findOperatorIdx( Array<XPathFunction*> operators, String find )
{
for( int i = 0; i < operators.getSize(); ++i ) {
if( operators[i]->getName() == find ) {
return (i);
}
}
return (-1);
}
}
// Functions ===============================================================================================================
namespace blue {
namespace ext {
namespace xml {
// ---------------------------------------------------------------------------------------------------------------------
XPathPredicate::XPathPredicate()
{
m_defaults.append( new XPathFunctionCount() );
m_defaults.append( new XPathFunctionLast() );
m_defaults.append( new XPathFunctionLocalName() );
m_defaults.append( new XPathFunctionName() );
m_defaults.append( new XPathFunctionPosition() );
m_defaults.append( new XPathFunctionConcat() );
m_defaults.append( new XPathFunctionContains() );
m_defaults.append( new XPathFunctionNormalizeSpace() );
m_defaults.append( new XPathFunctionStartsWith() );
m_defaults.append( new XPathFunctionString() );
m_defaults.append( new XPathFunctionStringLength() );
m_defaults.append( new XPathFunctionSubstring() );
m_defaults.append( new XPathFunctionSubstringAfter() );
m_defaults.append( new XPathFunctionSubstringBefore() );
m_defaults.append( new XPathFunctionTranslate() );
m_defaults.append( new XPathFunctionCeiling() );
m_defaults.append( new XPathFunctionFloor() );
m_defaults.append( new XPathFunctionRound() );
m_defaults.append( new XPathFunctionSum() );
m_defaults.append( new XPathFunctionBoolean() );
m_defaults.append( new XPathFunctionFalse() );
m_defaults.append( new XPathFunctionNot() );
m_defaults.append( new XPathFunctionTrue() );
m_operators.append( new XPathOperatorOr() );
m_operators.append( new XPathOperatorAnd() );
m_operators.append( new XPathOperatorEqual() );
m_operators.append( new XPathOperatorNotEqual() );
m_operators.append( new XPathOperatorLessEqual() );
m_operators.append( new XPathOperatorLess() );
m_operators.append( new XPathOperatorGreatEqual() );
m_operators.append( new XPathOperatorGreat() );
m_operators.append( new XPathOperatorAdd() );
m_operators.append( new XPathOperatorSub() );
m_operators.append( new XPathOperatorMult() );
m_operators.append( new XPathOperatorDiv() );
m_operators.append( new XPathOperatorMod() );
for( int iD = 0; iD < m_defaults.getSize(); ++iD ) {
addFunction(m_defaults[iD]);
}
}
// ---------------------------------------------------------------------------------------------------------------------
XPathPredicate::~XPathPredicate()
{
for( int iD = 0; iD < m_defaults.getSize(); ++iD ) {
delete m_defaults[iD];
}
for( int iO = 0; iO < m_operators.getSize(); ++iO ) {
delete m_operators[iO];
}
}
// ---------------------------------------------------------------------------------------------------------------------
Array<XPathToken> XPathPredicate::parsePredicate( String predicate )
{
StringTokenizer toker;
toker.addContainer($("\""), $("\""), StringTokenizer::EXCLUSIVE);
toker.addContainer($("\'"), $("\'"), StringTokenizer::EXCLUSIVE);
toker.addContainer($("["), $("]"), StringTokenizer::NORMAL);
toker.addContainer($("("), $(")"), StringTokenizer::NORMAL);
flags32_t tokerFlags = StringTokenizer::KEEP_DELIMITERS|StringTokenizer::NO_WHITESPACE|StringTokenizer::TRIM_RESULTS;
String delimiters = $(" (),+=-*!<>");
Array<String> predTokens = toker.tokenize(predicate, delimiters, tokerFlags);
// Tokenize into strings
int iT = 0;
while( iT < predTokens.getSize() ) {
Array<String> tokens = toker.tokenize(predTokens[iT], delimiters, tokerFlags);
if( tokens.getSize() > 1 ) {
predTokens.remove(iT);
for( int i = 0; i < tokens.getSize(); ++i ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -