30 : m_parent( 0 ), m_type(
StanzaUndefined ), m_incoming( false ), m_valid( false )
34 Tag::Tag(
const std::string& name,
const std::string& cdata,
bool incoming )
35 : m_name( incoming ? relax( name ) : name ),
36 m_cdata( incoming ? relax( cdata ) : cdata ),
37 m_parent( 0 ), m_type(
StanzaUndefined ), m_incoming( incoming ), m_valid( true )
39 m_valid = !m_name.empty();
42 Tag::Tag(
Tag *parent,
const std::string& name,
const std::string& cdata,
bool incoming )
43 : m_name( incoming ? relax( name ) : name ),
44 m_cdata( incoming ? relax( cdata ) : cdata ),
45 m_parent( parent ), m_type(
StanzaUndefined ), m_incoming( incoming ), m_valid( true )
49 m_valid = !m_name.empty();
52 Tag::Tag(
const std::string& name,
const std::string& attrib,
const std::string& value,
bool incoming )
53 : m_name( incoming ? relax( name ) : name ),
54 m_parent( 0 ), m_type(
StanzaUndefined ), m_incoming( incoming ), m_valid( true )
57 m_valid = !m_name.empty();
60 Tag::Tag(
Tag *parent,
const std::string& name,
const std::string& attrib,
const std::string& value,
62 : m_name( incoming ? relax( name ) : name ),
63 m_parent( parent ), m_type(
StanzaUndefined ), m_incoming( incoming ), m_valid( true )
68 m_valid = !m_name.empty();
73 TagList::iterator it = m_children.begin();
74 for( ; it != m_children.end(); ++it )
83 if( m_name != right.m_name || m_attribs != right.m_attribs
84 || m_children.size() != right.m_children.size() )
87 TagList::const_iterator it = m_children.begin();
88 TagList::const_iterator it_r = right.m_children.begin();
89 while( it != m_children.end() && it_r != right.m_children.end() && *(*it) == *(*it_r) )
94 return it == m_children.end();
99 std::string
xml =
"<";
101 if( !m_attribs.empty() )
103 AttributeList::const_iterator it_a = m_attribs.begin();
104 for( ; it_a != m_attribs.end(); ++it_a )
107 xml +=
escape( (*it_a).first );
109 xml +=
escape( (*it_a).second );
114 if( m_cdata.empty() && !m_children.size() )
116 else if( m_children.size() )
119 TagList::const_iterator it_c = m_children.begin();
120 for( ; it_c != m_children.end(); ++it_c )
122 xml += (*it_c)->xml();
128 else if( !m_cdata.empty() )
140 static const char escape_chars[] = {
'&',
'<',
'>',
'\'',
'"',
'<',
'>',
141 '\'',
'"',
'<',
'>',
'<',
'>',
'\'',
'"',
'<',
'>',
'<',
'>',
'\'',
'"' };
143 static const std::string escape_seqs[] = {
"amp;",
"lt;",
"gt;",
"apos;",
144 "quot;",
"#60;",
"#62;",
"#39;",
"#34;",
"#x3c;",
"#x3e;",
"#x3C;",
145 "#x3E;",
"#x27;",
"#x22;",
"#X3c;",
"#X3e;",
"#X3C;",
"#X3E;",
"#X27;",
148 static const unsigned nb_escape =
sizeof(escape_chars)/
sizeof(
char);
149 static const unsigned escape_size = 5;
153 for(
unsigned val, i = 0; i < esc.length(); ++i )
155 for( val = 0; val < escape_size; ++val )
157 if( esc[i] == escape_chars[val] )
160 esc.insert( i+1, escape_seqs[val] );
161 i += escape_seqs[val].length();
175 const unsigned int l = esc.length();
179 for(
unsigned int val; i < l; ++i )
184 for( val = 0; val < nb_escape; ++val )
186 if( ( i + escape_seqs[val].length() <= l )
187 && !strncmp( esc.data()+i+1, escape_seqs[val].data(),
188 escape_seqs[val].length() ) )
190 esc[i] = escape_chars[val];
191 for( p=1; p <= escape_seqs[val].length(); ++p )
200 for( p = 0, i = 0; i < l; ++i )
219 if( name.empty() || value.empty() )
222 AttributeList::iterator it = m_attribs.begin();
223 for( ; it != m_attribs.end(); ++it )
225 if( (*it).first == ( m_incoming ?
relax( name ) : name ) )
227 (*it).second = m_incoming ?
relax( value ) : value;
232 m_attribs.push_back(
Attribute( m_incoming ?
relax( name ) : name,
233 m_incoming ?
relax( value ) : value ) );
241 const int len = 4 + (int)std::log10( value ) + 1;
242 char *tmp =
new char[len];
243 sprintf( tmp,
"%d", value );
244 std::string ret( tmp, len );
248 std::ostringstream oss;
260 const int len = 4 + (int)std::log10( value ) + 1;
261 char *tmp =
new char[len];
262 sprintf( tmp,
"%ld", value );
263 std::string ret( tmp, len );
267 std::ostringstream oss;
278 m_children.push_back( child );
279 child->m_parent =
this;
288 m_children.push_back( t );
295 AttributeList::const_iterator it = m_attribs.begin();
296 for( ; it != m_attribs.end(); ++it )
297 if( (*it).first == ( m_incoming ?
relax( name ) : name ) )
300 return std::string();
308 AttributeList::const_iterator it = m_attribs.begin();
309 for( ; it != m_attribs.end(); ++it )
310 if( (*it).first == ( m_incoming ?
relax( name ) : name )
311 && ( value.empty() || (*it).second == ( m_incoming ?
relax( value ) : value ) ) )
319 TagList::const_iterator it = m_children.begin();
320 while( it != m_children.end() && (*it)->name() != ( m_incoming ?
relax( name ) :
name ) )
322 return it != m_children.end() ? (*it) : 0;
326 const std::string& value )
const
331 TagList::const_iterator it = m_children.begin();
332 while( it != m_children.end()
333 && ( (*it)->name() != ( m_incoming ?
relax( name ) :
name )
334 || ! (*it)->hasAttribute( attr, value ) ) )
336 return it != m_children.end() ? (*it) : 0;
341 TagList::const_iterator it = m_children.begin();
342 while( it != m_children.end() && ( (*it)->name() != ( m_incoming ?
relax( name ) :
name )
343 || ( !cdata.empty() && (*it)->cdata() != ( m_incoming ?
relax( cdata ) :
cdata ) ) ) )
345 return it != m_children.end();
350 TagList::const_iterator it = m_children.begin();
351 while( it != m_children.end() && ! (*it)->hasAttribute( attr, value ) )
353 return it != m_children.end() ? (*it) : 0;
359 t->m_attribs = m_attribs;
362 Tag::TagList::const_iterator it = m_children.begin();
363 for( ; it != m_children.end(); ++it )
379 Tag::TagList::const_iterator it = list.begin();
380 for( ; it != list.end(); ++it )
382 if( (*it)->name() == ( m_incoming ?
relax( name ) : name ) )
383 ret.push_back( (*it) );
391 return !l.empty() ? l.front() : 0;
397 if( expression ==
"/" || expression ==
"//" )
400 if( m_parent && expression.length() >= 2 && expression.substr( 0, 1 ) ==
"/"
401 && expression.substr( 1, 1 ) !=
"/" )
405 Tag *p = parse( expression, len );
408 l = evaluateTagList( p );
422 TokenType tokenType = (TokenType)atoi( token->
findAttribute(
"type" ).c_str() );
426 add( result, evaluateUnion( token ) );
435 if( tokenChildren.size() )
437 bool predicatesSucceeded =
true;
438 Tag::TagList::const_iterator cit = tokenChildren.begin();
439 for( ; cit != tokenChildren.end(); ++cit )
441 if( (*cit)->hasAttribute(
"predicate",
"true" ) )
443 predicatesSucceeded = evaluatePredicate( (*cit) );
444 if( !predicatesSucceeded )
449 bool hasElementChildren =
false;
450 cit = tokenChildren.begin();
451 for( ; cit != tokenChildren.end(); ++cit )
453 if( (*cit)->hasAttribute(
"predicate",
"true" ) ||
454 (*cit)->hasAttribute(
"number",
"true" ) )
457 hasElementChildren =
true;
460 if( !m_children.empty() )
462 Tag::TagList::const_iterator it = m_children.begin();
463 for( ; it != m_children.end(); ++it )
465 add( result, (*it)->evaluateTagList( (*cit) ) );
468 else if( atoi( (*cit)->findAttribute(
"type" ).c_str() ) == XTDoubleDot && m_parent )
470 (*cit)->addAttribute(
"type", XTDot );
471 add( result, m_parent->evaluateTagList( (*cit) ) );
475 if( !hasElementChildren )
476 result.push_back(
this );
481 result.push_back(
this );
495 add( result, evaluateTagList( t ) );
497 Tag::TagList::const_iterator it = res2.begin();
498 for( ; it != res2.end(); ++it )
500 add( result, (*it)->evaluateTagList( t ) );
508 if( !tokenChildren.empty() )
510 add( result, evaluateTagList( tokenChildren.front() ) );
513 result.push_back(
this );
522 if( tokenChildren.size() )
524 Tag *testtoken = tokenChildren.front();
525 if( testtoken->name() ==
"*" )
527 add( result, m_parent->evaluateTagList( testtoken ) );
533 t->m_name = m_parent->m_name;
534 add( result, m_parent->evaluateTagList( t ) );
540 result.push_back( m_parent );
552 int pos = atoi( token->
name().c_str() );
554 if( pos > 0 && pos <= (
int)res.size() )
556 Tag::TagList::const_iterator it = res.begin();
561 result.push_back( *it );
571 bool Tag::evaluateBoolean( Tag *token )
577 TokenType tokenType = (TokenType)atoi( token->findAttribute(
"type" ).c_str() );
581 if( token->name() ==
"*" && m_attribs.size() )
587 result = evaluateEquals( token );
601 t->addAttribute(
"type", XTDot );
602 t->addChild( token );
603 result = !evaluateTagList( t ).empty();
604 t->removeChild( token );
615 bool Tag::evaluateEquals( Tag *token )
617 if( !token || token->children().size() != 2 )
621 Tag::TagList::const_iterator it = token->children().begin();
625 TokenType tt1 = (TokenType)atoi( ch1->findAttribute(
"type" ).c_str() );
626 TokenType tt2 = (TokenType)atoi( ch2->findAttribute(
"type" ).c_str() );
653 result = ( ch1->name() == ch2->name() );
669 Tag::TagList::const_iterator it = m_children.begin();
670 for( ; it != m_children.end(); ++it )
672 result.push_back( (*it) );
673 add( result, (*it)->allDescendants() );
685 Tag::TagList::const_iterator it = l.begin();
686 for( ; it != l.end(); ++it )
688 add( result, evaluateTagList( (*it) ) );
693 void Tag::closePreviousToken( Tag** root, Tag** current, Tag::TokenType& type, std::string& tok )
697 addToken( root, current, type, tok );
703 Tag* Tag::parse(
const std::string& expression,
unsigned& len, Tag::TokenType border )
715 Tag::TokenType type = XTElement;
718 for( ; len < expression.length(); ++len )
721 if( type == XTLiteralInside && c !=
'\'' )
730 closePreviousToken( &root, ¤t, type, token );
732 if( len < expression.length()-1 && expression[len+1] ==
'/' )
735 type = XTDoubleSlash;
745 closePreviousToken( &root, ¤t, type, token );
750 closePreviousToken( &root, ¤t, type, token );
751 Tag *t = parse( expression, ++len, XTRightBracket );
752 if( !addPredicate( &root, ¤t, t ) )
758 closePreviousToken( &root, ¤t, type, token );
759 Tag *t = parse( expression, ++len, XTRightParenthesis );
763 t->addAttribute(
"argument",
"true" );
764 current->addChild( t );
774 closePreviousToken( &root, ¤t, type, token );
778 if( type == XTLiteralInside )
779 if( expression[len - 2] ==
'\\' )
780 token[token.length() - 2] = c;
784 type = XTLiteralInside;
791 if( token.size() == 1 )
793 if( len < expression.length()-1 && expression[len+1] ==
'.' )
812 addToken( &root, ¤t, type,
"*" );
821 closePreviousToken( &root, ¤t, type, token );
822 std::string s( 1, c );
823 Tag::TokenType ttype = getType( s );
824 if( ttype <= border )
826 Tag *t = parse( expression, ++len, ttype );
827 addOperator( &root, ¤t, t, ttype, s );
828 if( border == XTRightBracket )
838 addToken( &root, ¤t, type, token );
845 void Tag::addToken( Tag **root, Tag **current, Tag::TokenType type,
846 const std::string& token )
848 Tag *t =
new Tag( token );
849 if( t->isNumber() && !t->children().size() )
851 t->addAttribute(
"type", type );
856 (*current)->addChild( t );
862 *current = *root = t;
866 void Tag::addOperator( Tag **root, Tag **current, Tag *arg,
867 Tag::TokenType type,
const std::string& token )
869 Tag *t =
new Tag( token );
870 t->addAttribute(
"type", type );
873 t->addAttribute(
"operator",
"true" );
874 t->addChild( *root );
876 *current = *root = t;
879 bool Tag::addPredicate( Tag **root, Tag **current, Tag *token )
881 if( !*root || !*current )
884 if( ( token->isNumber() && !token->children().size() ) || token->name() ==
"+" )
887 if( !token->hasAttribute(
"operator",
"true" ) )
889 token->addAttribute(
"type", XTInteger );
891 if( *root == *current )
898 (*root)->removeChild( *current );
899 (*root)->addChild( token );
902 token->addChild( *current );
907 token->addAttribute(
"predicate",
"true" );
908 (*current)->addChild( token );
914 Tag::TokenType Tag::getType(
const std::string& c )
923 return XTOperatorMul;
925 return XTOperatorPlus;
932 bool Tag::isWhitespace(
const char c )
934 return ( c == 0x09 || c == 0x0a || c == 0x0d || c == 0x20 );
942 std::string::size_type l = m_name.length();
943 std::string::size_type i = 0;
944 while( i < l && isdigit( m_name[i] ) )
951 Tag::TagList::const_iterator it = two.begin();
952 for( ; it != two.end(); ++it )
953 if( std::find( one.begin(), one.end(), (*it) ) == one.end() )
954 one.push_back( (*it) );