📄 tag.cpp
字号:
// printf( "adding %s to result set\n", name().c_str() ); result.push_back( this ); } }// else// printf( "found %s != %s\n", token->name().c_str(), name().c_str() ); break; } case XTDoubleSlash: {// printf( "in XTDoubleSlash\n" ); Tag *t = token->clone();// printf( "original token: %s\ncloned token: %s\n", token->xml().c_str(), n->xml().c_str() ); t->addAttribute( "type", XTElement ); add( result, evaluateTagList( t ) ); const Tag::TagList& res2 = allDescendants(); Tag::TagList::const_iterator it = res2.begin(); for( ; it != res2.end(); ++it ) { add( result, (*it)->evaluateTagList( t ) ); } delete t; break; } case XTDot: { const Tag::TagList& tokenChildren = token->children(); if( !tokenChildren.empty() ) { add( result, evaluateTagList( tokenChildren.front() ) ); } else result.push_back( this ); break; } case XTDoubleDot: {// printf( "in XTDoubleDot\n" ); if( m_parent ) { const Tag::TagList& tokenChildren = token->children(); if( tokenChildren.size() ) { Tag *testtoken = tokenChildren.front(); if( testtoken->name() == "*" ) { add( result, m_parent->evaluateTagList( testtoken ) ); } else { Tag *t = token->clone(); t->addAttribute( "type", XTElement ); t->m_name = m_parent->m_name; add( result, m_parent->evaluateTagList( t ) ); delete t; } } else { result.push_back( m_parent ); } } } case XTInteger: { const Tag::TagList& l = token->children(); if( !l.size() ) break; const Tag::TagList& res = evaluateTagList( l.front() ); int pos = atoi( token->name().c_str() );// printf( "checking index %d\n", pos ); if( pos > 0 && pos <= (int)res.size() ) { Tag::TagList::const_iterator it = res.begin(); while ( --pos ) { ++it; } result.push_back( *it ); } break; } default: break; } return result; } bool Tag::evaluateBoolean( Tag *token ) { if( !token ) return false; bool result = false; TokenType tokenType = (TokenType)atoi( token->findAttribute( "type" ).c_str() ); switch( tokenType ) { case XTAttribute: if( token->name() == "*" && m_attribs.size() ) result = true; else result = hasAttribute( token->name() ); break; case XTOperatorEq: result = evaluateEquals( token ); break; case XTOperatorLt: break; case XTOperatorLtEq: break; case XTOperatorGtEq: break; case XTOperatorGt: break; case XTUnion: case XTElement: { Tag *t = new Tag( "." ); t->addAttribute( "type", XTDot ); t->addChild( token ); result = !evaluateTagList( t ).empty(); t->removeChild( token ); delete t; break; } default: break; } return result; } bool Tag::evaluateEquals( Tag *token ) { if( !token || token->children().size() != 2 ) return false; bool result = false; Tag::TagList::const_iterator it = token->children().begin(); Tag *ch1 = (*it); Tag *ch2 = (*++it); TokenType tt1 = (TokenType)atoi( ch1->findAttribute( "type" ).c_str() ); TokenType tt2 = (TokenType)atoi( ch2->findAttribute( "type" ).c_str() ); switch( tt1 ) { case XTAttribute: switch( tt2 ) { case XTInteger: case XTLiteral: result = ( findAttribute( ch1->name() ) == ch2->name() ); break; case XTAttribute: result = ( hasAttribute( ch1->name() ) && hasAttribute( ch2->name() ) && findAttribute( ch1->name() ) == findAttribute( ch2->name() ) ); break; default: break; } break; case XTInteger: case XTLiteral: switch( tt2 ) { case XTAttribute: result = ( ch1->name() == findAttribute( ch2->name() ) ); break; case XTLiteral: case XTInteger: result = ( ch1->name() == ch2->name() ); break; default: break; } break; default: break; } return result; } Tag::TagList Tag::allDescendants() { Tag::TagList result; Tag::TagList::const_iterator it = m_children.begin(); for( ; it != m_children.end(); ++it ) { result.push_back( (*it) ); add( result, (*it)->allDescendants() ); } return result; } Tag::TagList Tag::evaluateUnion( Tag *token ) { Tag::TagList result; if( !token ) return result; const Tag::TagList& l = token->children(); Tag::TagList::const_iterator it = l.begin(); for( ; it != l.end(); ++it ) { add( result, evaluateTagList( (*it) ) ); } return result; } void Tag::closePreviousToken( Tag** root, Tag** current, Tag::TokenType& type, std::string& tok ) { if( !tok.empty() ) { addToken( root, current, type, tok ); type = XTElement; tok = ""; } } Tag* Tag::parse( const std::string& expression, unsigned& len, Tag::TokenType border ) { Tag *root = 0; Tag *current = root; std::string token;// XPathError error = XPNoError;// XPathState state = Init;// int expected = 0;// bool run = true;// bool ws = false; Tag::TokenType type = XTElement; char c; for( ; len < expression.length(); ++len ) { c = expression[len]; if( type == XTLiteralInside && c != '\'' ) { token += c; continue; } switch( c ) { case '/': closePreviousToken( &root, ¤t, type, token ); if( len < expression.length()-1 && expression[len+1] == '/' ) {// addToken( &root, ¤t, XTDoubleSlash, "//" ); type = XTDoubleSlash; ++len; }// else// {// if( !current )// addToken( &root, ¤t, XTSlash, "/" );// } break; case ']': closePreviousToken( &root, ¤t, type, token ); ++len; return root; case '[': { closePreviousToken( &root, ¤t, type, token ); Tag *t = parse( expression, ++len, XTRightBracket ); if( !addPredicate( &root, ¤t, t ) ) delete t; break; } case '(': { closePreviousToken( &root, ¤t, type, token ); Tag *t = parse( expression, ++len, XTRightParenthesis ); if( current ) {// printf( "added %s to %s\n", t->xml().c_str(), current->xml().c_str() ); t->addAttribute( "argument", "true" ); current->addChild( t ); } else { root = t;// printf( "made %s new root\n", t->xml().c_str() ); } break; } case ')': closePreviousToken( &root, ¤t, type, token ); ++len; return root; case '\'': if( type == XTLiteralInside ) if( expression[len - 2] == '\\' ) token[token.length() - 2] = c; else type = XTLiteral; else type = XTLiteralInside; break; case '@': type = XTAttribute; break; case '.': token += c; if( token.size() == 1 ) { if( len < expression.length()-1 && expression[len+1] == '.' ) { type = XTDoubleDot; ++len; token += c; } else { type = XTDot; } } break; case '*':// if( !root || ( current && ( current->tokenType() == XTSlash// || current->tokenType() == XTDoubleSlash ) ) )// {// addToken( &root, ¤t, type, "*" );// break;// } addToken( &root, ¤t, type, "*" ); type = XTElement; break; case '+': case '>': case '<': case '=': case '|': { closePreviousToken( &root, ¤t, type, token ); std::string s( 1, c ); Tag::TokenType ttype = getType( s ); if( ttype <= border ) return root; Tag *t = parse( expression, ++len, ttype ); addOperator( &root, ¤t, t, ttype, s ); if( border == XTRightBracket ) return root; break; } default: token += c; } } if( !token.empty() ) addToken( &root, ¤t, type, token );// if( error != XPNoError )// printf( "error: %d\n", error ); return root; } void Tag::addToken( Tag **root, Tag **current, Tag::TokenType type, const std::string& token ) { Tag *t = new Tag( token ); if( t->isNumber() && !t->children().size() ) type = XTInteger; t->addAttribute( "type", type ); if( *root ) {// printf( "new current %s, type: %d\n", token.c_str(), type ); (*current)->addChild( t ); *current = t; } else {// printf( "new root %s, type: %d\n", token.c_str(), type ); *current = *root = t; } } void Tag::addOperator( Tag **root, Tag **current, Tag *arg, Tag::TokenType type, const std::string& token ) { Tag *t = new Tag( token ); t->addAttribute( "type", type );// printf( "new operator: %s (arg1: %s, arg2: %s)\n", t->name().c_str(), (*root)->xml().c_str(),// arg->xml().c_str() ); t->addAttribute( "operator", "true" ); t->addChild( *root ); t->addChild( arg ); *current = *root = t; } bool Tag::addPredicate( Tag **root, Tag **current, Tag *token ) { if( !*root || !*current ) return false; if( ( token->isNumber() && !token->children().size() ) || token->name() == "+" ) {// printf( "found Index %s, full: %s\n", token->name().c_str(), token->xml().c_str() ); if( !token->hasAttribute( "operator", "true" ) ) { token->addAttribute( "type", XTInteger ); } if( *root == *current ) { *root = token;// printf( "made Index new root\n" ); } else { (*root)->removeChild( *current ); (*root)->addChild( token );// printf( "added Index somewhere between root and current\n" ); } token->addChild( *current );// printf( "added Index %s, full: %s\n", token->name().c_str(), token->xml().c_str() ); } else { token->addAttribute( "predicate", "true" ); (*current)->addChild( token ); } return true; } Tag::TokenType Tag::getType( const std::string& c ) { if( c == "|" ) return XTUnion; if( c == "<" ) return XTOperatorLt; if( c == ">" ) return XTOperatorGt; if( c == "*" ) return XTOperatorMul; if( c == "+" ) return XTOperatorPlus; if( c == "=" ) return XTOperatorEq; return XTNone; } bool Tag::isWhitespace( const char c ) { return ( c == 0x09 || c == 0x0a || c == 0x0d || c == 0x20 ); } bool Tag::isNumber() { if( m_name.empty() ) return false; std::string::size_type l = m_name.length(); std::string::size_type i = 0; while( i < l && isdigit( m_name[i] ) ) ++i; return i == l; } void Tag::add( Tag::TagList& one, const Tag::TagList& two ) { Tag::TagList::const_iterator it = two.begin(); for( ; it != two.end(); ++it ) if( std::find( one.begin(), one.end(), (*it) ) == one.end() ) one.push_back( (*it) ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -