00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "tag.h"
00015
00016 #include <stdlib.h>
00017
00018 #ifdef _WIN32_WCE
00019 # include <cmath>
00020 #else
00021 # include <sstream>
00022 #endif
00023
00024 #include <algorithm>
00025 #include <cstring>
00026
00027 namespace gloox
00028 {
00029 Tag::Tag()
00030 : m_parent( 0 ), m_type( StanzaUndefined ), m_incoming( false ), m_valid( false )
00031 {
00032 }
00033
00034 Tag::Tag( const std::string& name, const std::string& cdata, bool incoming )
00035 : m_name( incoming ? relax( name ) : name ),
00036 m_cdata( incoming ? relax( cdata ) : cdata ),
00037 m_parent( 0 ), m_type( StanzaUndefined ), m_incoming( incoming ), m_valid( true )
00038 {
00039 m_valid = !m_name.empty();
00040 }
00041
00042 Tag::Tag( Tag *parent, const std::string& name, const std::string& cdata, bool incoming )
00043 : m_name( incoming ? relax( name ) : name ),
00044 m_cdata( incoming ? relax( cdata ) : cdata ),
00045 m_parent( parent ), m_type( StanzaUndefined ), m_incoming( incoming ), m_valid( true )
00046 {
00047 if( m_parent )
00048 m_parent->addChild( this );
00049 m_valid = !m_name.empty();
00050 }
00051
00052 Tag::Tag( const std::string& name, const std::string& attrib, const std::string& value, bool incoming )
00053 : m_name( incoming ? relax( name ) : name ),
00054 m_parent( 0 ), m_type( StanzaUndefined ), m_incoming( incoming ), m_valid( true )
00055 {
00056 addAttribute( attrib, value );
00057 m_valid = !m_name.empty();
00058 }
00059
00060 Tag::Tag( Tag *parent, const std::string& name, const std::string& attrib, const std::string& value,
00061 bool incoming )
00062 : m_name( incoming ? relax( name ) : name ),
00063 m_parent( parent ), m_type( StanzaUndefined ), m_incoming( incoming ), m_valid( true )
00064 {
00065 if( m_parent )
00066 m_parent->addChild( this );
00067 addAttribute( attrib, value );
00068 m_valid = !m_name.empty();
00069 }
00070
00071 Tag::~Tag()
00072 {
00073 TagList::iterator it = m_children.begin();
00074 for( ; it != m_children.end(); ++it )
00075 {
00076 delete (*it);
00077 }
00078 m_parent = 0;
00079 }
00080
00081 bool Tag::operator==( const Tag &right ) const
00082 {
00083 if( m_name != right.m_name || m_attribs != right.m_attribs
00084 || m_children.size() != right.m_children.size() )
00085 return false;
00086
00087 TagList::const_iterator it = m_children.begin();
00088 TagList::const_iterator it_r = right.m_children.begin();
00089 while( it != m_children.end() && it_r != right.m_children.end() && *(*it) == *(*it_r) )
00090 {
00091 ++it;
00092 ++it_r;
00093 }
00094 return it == m_children.end();
00095 }
00096
00097 const std::string Tag::xml() const
00098 {
00099 std::string xml = "<";
00100 xml += escape( m_name );
00101 if( !m_attribs.empty() )
00102 {
00103 AttributeList::const_iterator it_a = m_attribs.begin();
00104 for( ; it_a != m_attribs.end(); ++it_a )
00105 {
00106 xml += " ";
00107 xml += escape( (*it_a).first );
00108 xml += "='";
00109 xml += escape( (*it_a).second );
00110 xml += "'";
00111 }
00112 }
00113
00114 if( m_cdata.empty() && !m_children.size() )
00115 xml += "/>";
00116 else if( m_children.size() )
00117 {
00118 xml += ">";
00119 TagList::const_iterator it_c = m_children.begin();
00120 for( ; it_c != m_children.end(); ++it_c )
00121 {
00122 xml += (*it_c)->xml();
00123 }
00124 xml += "</";
00125 xml += escape( m_name );
00126 xml += ">";
00127 }
00128 else if( !m_cdata.empty() )
00129 {
00130 xml += ">";
00131 xml += escape( m_cdata );
00132 xml += "</";
00133 xml += escape( m_name );
00134 xml += ">";
00135 }
00136
00137 return xml;
00138 }
00139
00140 static const char escape_chars[] = { '&', '<', '>', '\'', '"', '<', '>',
00141 '\'', '"', '<', '>', '<', '>', '\'', '"', '<', '>', '<', '>', '\'', '"' };
00142
00143 static const std::string escape_seqs[] = { "amp;", "lt;", "gt;", "apos;",
00144 "quot;", "#60;", "#62;", "#39;", "#34;", "#x3c;", "#x3e;", "#x3C;",
00145 "#x3E;", "#x27;", "#x22;", "#X3c;", "#X3e;", "#X3C;", "#X3E;", "#X27;",
00146 "#X22;" };
00147
00148 static const unsigned nb_escape = sizeof(escape_chars)/sizeof(char);
00149 static const unsigned escape_size = 5;
00150
00151 const std::string Tag::escape( std::string esc )
00152 {
00153 for( unsigned val, i = 0; i < esc.length(); ++i )
00154 {
00155 for( val = 0; val < escape_size; ++val )
00156 {
00157 if( esc[i] == escape_chars[val] )
00158 {
00159 esc[i] = '&';
00160 esc.insert( i+1, escape_seqs[val] );
00161 i += escape_seqs[val].length();
00162 break;
00163 }
00164 }
00165 }
00166 return esc;
00167 }
00168
00169
00170
00171
00172
00173 const std::string Tag::relax( std::string esc )
00174 {
00175 const unsigned int l = esc.length();
00176 unsigned int p = 0;
00177 unsigned int i = 0;
00178
00179 for( unsigned int val; i < l; ++i )
00180 {
00181 if( esc[i] != '&' )
00182 continue;
00183
00184 for( val = 0; val < nb_escape; ++val )
00185 {
00186 if( ( i + escape_seqs[val].length() <= l )
00187 && !strncmp( esc.data()+i+1, escape_seqs[val].data(),
00188 escape_seqs[val].length() ) )
00189 {
00190 esc[i] = escape_chars[val];
00191 for( p=1; p <= escape_seqs[val].length(); ++p )
00192 esc[i+p] = 0;
00193 i += p-1;
00194 break;
00195 }
00196 }
00197 }
00198 if( p )
00199 {
00200 for( p = 0, i = 0; i < l; ++i )
00201 {
00202 if( esc[i] != 0 )
00203 {
00204 if( esc[p] == 0 )
00205 {
00206 esc[p] = esc[i];
00207 esc[p+1] = 0;
00208 }
00209 ++p;
00210 }
00211 }
00212 esc.resize( p );
00213 }
00214 return esc;
00215 }
00216
00217 void Tag::addAttribute( const std::string& name, const std::string& value )
00218 {
00219 if( name.empty() || value.empty() )
00220 return;
00221
00222 AttributeList::iterator it = m_attribs.begin();
00223 for( ; it != m_attribs.end(); ++it )
00224 {
00225 if( (*it).first == ( m_incoming ? relax( name ) : name ) )
00226 {
00227 (*it).second = m_incoming ? relax( value ) : value;
00228 return;
00229 }
00230 }
00231
00232 m_attribs.push_back( Attribute( m_incoming ? relax( name ) : name,
00233 m_incoming ? relax( value ) : value ) );
00234 }
00235
00236 void Tag::addAttribute( const std::string& name, int value )
00237 {
00238 if( !name.empty() )
00239 {
00240 #ifdef _WIN32_WCE
00241 const int len = 4 + (int)std::log10( value ) + 1;
00242 char *tmp = new char[len];
00243 sprintf( tmp, "%d", value );
00244 std::string ret( tmp, len );
00245 addAttribute( name, ret );
00246 delete[] tmp;
00247 #else
00248 std::ostringstream oss;
00249 oss << value;
00250 addAttribute( name, oss.str() );
00251 #endif
00252 }
00253 }
00254
00255 void Tag::addAttribute( const std::string& name, long value )
00256 {
00257 if( !name.empty() )
00258 {
00259 #ifdef _WIN32_WCE
00260 const int len = 4 + (int)std::log10( value ) + 1;
00261 char *tmp = new char[len];
00262 sprintf( tmp, "%ld", value );
00263 std::string ret( tmp, len );
00264 addAttribute( name, ret );
00265 delete[] tmp;
00266 #else
00267 std::ostringstream oss;
00268 oss << value;
00269 addAttribute( name, oss.str() );
00270 #endif
00271 }
00272 }
00273
00274 void Tag::addChild( Tag *child )
00275 {
00276 if( child )
00277 {
00278 m_children.push_back( child );
00279 child->m_parent = this;
00280 }
00281 }
00282
00283 void Tag::addChildCopy( const Tag *child )
00284 {
00285 if( child )
00286 {
00287 Tag *t = child->clone();
00288 m_children.push_back( t );
00289 t->m_parent = this;
00290 }
00291 }
00292
00293 const std::string Tag::findAttribute( const std::string& name ) const
00294 {
00295 AttributeList::const_iterator it = m_attribs.begin();
00296 for( ; it != m_attribs.end(); ++it )
00297 if( (*it).first == ( m_incoming ? relax( name ) : name ) )
00298 return (*it).second;
00299
00300 return std::string();
00301 }
00302
00303 bool Tag::hasAttribute( const std::string& name, const std::string& value ) const
00304 {
00305 if( name.empty() )
00306 return true;
00307
00308 AttributeList::const_iterator it = m_attribs.begin();
00309 for( ; it != m_attribs.end(); ++it )
00310 if( (*it).first == ( m_incoming ? relax( name ) : name )
00311 && ( value.empty() || (*it).second == ( m_incoming ? relax( value ) : value ) ) )
00312 return true;
00313
00314 return false;
00315 }
00316
00317 Tag* Tag::findChild( const std::string& name ) const
00318 {
00319 TagList::const_iterator it = m_children.begin();
00320 while( it != m_children.end() && (*it)->name() != ( m_incoming ? relax( name ) : name ) )
00321 ++it;
00322 return it != m_children.end() ? (*it) : 0;
00323 }
00324
00325 Tag* Tag::findChild( const std::string& name, const std::string& attr,
00326 const std::string& value ) const
00327 {
00328 if( name.empty() )
00329 return 0;
00330
00331 TagList::const_iterator it = m_children.begin();
00332 while( it != m_children.end()
00333 && ( (*it)->name() != ( m_incoming ? relax( name ) : name )
00334 || ! (*it)->hasAttribute( attr, value ) ) )
00335 ++it;
00336 return it != m_children.end() ? (*it) : 0;
00337 }
00338
00339 bool Tag::hasChildWithCData( const std::string& name, const std::string& cdata ) const
00340 {
00341 TagList::const_iterator it = m_children.begin();
00342 while( it != m_children.end() && ( (*it)->name() != ( m_incoming ? relax( name ) : name )
00343 || ( !cdata.empty() && (*it)->cdata() != ( m_incoming ? relax( cdata ) : cdata ) ) ) )
00344 ++it;
00345 return it != m_children.end();
00346 }
00347
00348 Tag* Tag::findChildWithAttrib( const std::string& attr, const std::string& value ) const
00349 {
00350 TagList::const_iterator it = m_children.begin();
00351 while( it != m_children.end() && ! (*it)->hasAttribute( attr, value ) )
00352 ++it;
00353 return it != m_children.end() ? (*it) : 0;
00354 }
00355
00356 Tag* Tag::clone() const
00357 {
00358 Tag *t = new Tag( name(), cdata(), m_incoming );
00359 t->m_attribs = m_attribs;
00360 t->m_type = m_type;
00361
00362 Tag::TagList::const_iterator it = m_children.begin();
00363 for( ; it != m_children.end(); ++it )
00364 {
00365 t->addChild( (*it)->clone() );
00366 }
00367
00368 return t;
00369 }
00370
00371 Tag::TagList Tag::findChildren( const std::string& name ) const
00372 {
00373 return findChildren( m_children, name );
00374 }
00375
00376 Tag::TagList Tag::findChildren( const Tag::TagList& list, const std::string& name ) const
00377 {
00378 Tag::TagList ret;
00379 Tag::TagList::const_iterator it = list.begin();
00380 for( ; it != list.end(); ++it )
00381 {
00382 if( (*it)->name() == ( m_incoming ? relax( name ) : name ) )
00383 ret.push_back( (*it) );
00384 }
00385 return ret;
00386 }
00387
00388 Tag* Tag::findTag( const std::string& expression )
00389 {
00390 const Tag::TagList& l = findTagList( expression );
00391 return !l.empty() ? l.front() : 0;
00392 }
00393
00394 Tag::TagList Tag::findTagList( const std::string& expression )
00395 {
00396 Tag::TagList l;
00397 if( expression == "/" || expression == "//" )
00398 return l;
00399
00400 if( m_parent && expression.length() >= 2 && expression.substr( 0, 1 ) == "/"
00401 && expression.substr( 1, 1 ) != "/" )
00402 return m_parent->findTagList( expression );
00403
00404 unsigned len = 0;
00405 Tag *p = parse( expression, len );
00406
00407
00408 l = evaluateTagList( p );
00409 delete p;
00410 return l;
00411 }
00412
00413 Tag::TagList Tag::evaluateTagList( Tag *token )
00414 {
00415 Tag::TagList result;
00416 if( !token )
00417 return result;
00418
00419
00420
00421
00422 TokenType tokenType = (TokenType)atoi( token->findAttribute( "type" ).c_str() );
00423 switch( tokenType )
00424 {
00425 case XTUnion:
00426 add( result, evaluateUnion( token ) );
00427 break;
00428 case XTElement:
00429 {
00430
00431 if( token->name() == name() || token->name() == "*" )
00432 {
00433
00434 const Tag::TagList& tokenChildren = token->children();
00435 if( tokenChildren.size() )
00436 {
00437 bool predicatesSucceeded = true;
00438 Tag::TagList::const_iterator cit = tokenChildren.begin();
00439 for( ; cit != tokenChildren.end(); ++cit )
00440 {
00441 if( (*cit)->hasAttribute( "predicate", "true" ) )
00442 {
00443 predicatesSucceeded = evaluatePredicate( (*cit) );
00444 if( !predicatesSucceeded )
00445 return result;
00446 }
00447 }
00448
00449 bool hasElementChildren = false;
00450 cit = tokenChildren.begin();
00451 for( ; cit != tokenChildren.end(); ++cit )
00452 {
00453 if( (*cit)->hasAttribute( "predicate", "true" ) ||
00454 (*cit)->hasAttribute( "number", "true" ) )
00455 continue;
00456
00457 hasElementChildren = true;
00458
00459
00460 if( !m_children.empty() )
00461 {
00462 Tag::TagList::const_iterator it = m_children.begin();
00463 for( ; it != m_children.end(); ++it )
00464 {
00465 add( result, (*it)->evaluateTagList( (*cit) ) );
00466 }
00467 }
00468 else if( atoi( (*cit)->findAttribute( "type" ).c_str() ) == XTDoubleDot && m_parent )
00469 {
00470 (*cit)->addAttribute( "type", XTDot );
00471 add( result, m_parent->evaluateTagList( (*cit) ) );
00472 }
00473 }
00474
00475 if( !hasElementChildren )
00476 result.push_back( this );
00477 }
00478 else
00479 {
00480
00481 result.push_back( this );
00482 }
00483 }
00484
00485
00486
00487 break;
00488 }
00489 case XTDoubleSlash:
00490 {
00491
00492 Tag *t = token->clone();
00493
00494 t->addAttribute( "type", XTElement );
00495 add( result, evaluateTagList( t ) );
00496 const Tag::TagList& res2 = allDescendants();
00497 Tag::TagList::const_iterator it = res2.begin();
00498 for( ; it != res2.end(); ++it )
00499 {
00500 add( result, (*it)->evaluateTagList( t ) );
00501 }
00502 delete t;
00503 break;
00504 }
00505 case XTDot:
00506 {
00507 const Tag::TagList& tokenChildren = token->children();
00508 if( !tokenChildren.empty() )
00509 {
00510 add( result, evaluateTagList( tokenChildren.front() ) );
00511 }
00512 else
00513 result.push_back( this );
00514 break;
00515 }
00516 case XTDoubleDot:
00517 {
00518
00519 if( m_parent )
00520 {
00521 const Tag::TagList& tokenChildren = token->children();
00522 if( tokenChildren.size() )
00523 {
00524 Tag *testtoken = tokenChildren.front();
00525 if( testtoken->name() == "*" )
00526 {
00527 add( result, m_parent->evaluateTagList( testtoken ) );
00528 }
00529 else
00530 {
00531 Tag *t = token->clone();
00532 t->addAttribute( "type", XTElement );
00533 t->m_name = m_parent->m_name;
00534 add( result, m_parent->evaluateTagList( t ) );
00535 delete t;
00536 }
00537 }
00538 else
00539 {
00540 result.push_back( m_parent );
00541 }
00542 }
00543 }
00544 case XTInteger:
00545 {
00546 const Tag::TagList& l = token->children();
00547 if( !l.size() )
00548 break;
00549
00550 const Tag::TagList& res = evaluateTagList( l.front() );
00551
00552 int pos = atoi( token->name().c_str() );
00553
00554 if( pos > 0 && pos <= (int)res.size() )
00555 {
00556 Tag::TagList::const_iterator it = res.begin();
00557 while ( --pos )
00558 {
00559 ++it;
00560 }
00561 result.push_back( *it );
00562 }
00563 break;
00564 }
00565 default:
00566 break;
00567 }
00568 return result;
00569 }
00570
00571 bool Tag::evaluateBoolean( Tag *token )
00572 {
00573 if( !token )
00574 return false;
00575
00576 bool result = false;
00577 TokenType tokenType = (TokenType)atoi( token->findAttribute( "type" ).c_str() );
00578 switch( tokenType )
00579 {
00580 case XTAttribute:
00581 if( token->name() == "*" && m_attribs.size() )
00582 result = true;
00583 else
00584 result = hasAttribute( token->name() );
00585 break;
00586 case XTOperatorEq:
00587 result = evaluateEquals( token );
00588 break;
00589 case XTOperatorLt:
00590 break;
00591 case XTOperatorLtEq:
00592 break;
00593 case XTOperatorGtEq:
00594 break;
00595 case XTOperatorGt:
00596 break;
00597 case XTUnion:
00598 case XTElement:
00599 {
00600 Tag *t = new Tag( "." );
00601 t->addAttribute( "type", XTDot );
00602 t->addChild( token );
00603 result = !evaluateTagList( t ).empty();
00604 t->removeChild( token );
00605 delete t;
00606 break;
00607 }
00608 default:
00609 break;
00610 }
00611
00612 return result;
00613 }
00614
00615 bool Tag::evaluateEquals( Tag *token )
00616 {
00617 if( !token || token->children().size() != 2 )
00618 return false;
00619
00620 bool result = false;
00621 Tag::TagList::const_iterator it = token->children().begin();
00622 Tag *ch1 = (*it);
00623 Tag *ch2 = (*++it);
00624
00625 TokenType tt1 = (TokenType)atoi( ch1->findAttribute( "type" ).c_str() );
00626 TokenType tt2 = (TokenType)atoi( ch2->findAttribute( "type" ).c_str() );
00627 switch( tt1 )
00628 {
00629 case XTAttribute:
00630 switch( tt2 )
00631 {
00632 case XTInteger:
00633 case XTLiteral:
00634 result = ( findAttribute( ch1->name() ) == ch2->name() );
00635 break;
00636 case XTAttribute:
00637 result = ( hasAttribute( ch1->name() ) && hasAttribute( ch2->name() ) &&
00638 findAttribute( ch1->name() ) == findAttribute( ch2->name() ) );
00639 break;
00640 default:
00641 break;
00642 }
00643 break;
00644 case XTInteger:
00645 case XTLiteral:
00646 switch( tt2 )
00647 {
00648 case XTAttribute:
00649 result = ( ch1->name() == findAttribute( ch2->name() ) );
00650 break;
00651 case XTLiteral:
00652 case XTInteger:
00653 result = ( ch1->name() == ch2->name() );
00654 break;
00655 default:
00656 break;
00657 }
00658 break;
00659 default:
00660 break;
00661 }
00662
00663 return result;
00664 }
00665
00666 Tag::TagList Tag::allDescendants()
00667 {
00668 Tag::TagList result;
00669 Tag::TagList::const_iterator it = m_children.begin();
00670 for( ; it != m_children.end(); ++it )
00671 {
00672 result.push_back( (*it) );
00673 add( result, (*it)->allDescendants() );
00674 }
00675 return result;
00676 }
00677
00678 Tag::TagList Tag::evaluateUnion( Tag *token )
00679 {
00680 Tag::TagList result;
00681 if( !token )
00682 return result;
00683
00684 const Tag::TagList& l = token->children();
00685 Tag::TagList::const_iterator it = l.begin();
00686 for( ; it != l.end(); ++it )
00687 {
00688 add( result, evaluateTagList( (*it) ) );
00689 }
00690 return result;
00691 }
00692
00693 void Tag::closePreviousToken( Tag** root, Tag** current, Tag::TokenType& type, std::string& tok )
00694 {
00695 if( !tok.empty() )
00696 {
00697 addToken( root, current, type, tok );
00698 type = XTElement;
00699 tok = "";
00700 }
00701 }
00702
00703 Tag* Tag::parse( const std::string& expression, unsigned& len, Tag::TokenType border )
00704 {
00705 Tag *root = 0;
00706 Tag *current = root;
00707 std::string token;
00708
00709
00710
00711
00712
00713
00714
00715 Tag::TokenType type = XTElement;
00716
00717 char c;
00718 for( ; len < expression.length(); ++len )
00719 {
00720 c = expression[len];
00721 if( type == XTLiteralInside && c != '\'' )
00722 {
00723 token += c;
00724 continue;
00725 }
00726
00727 switch( c )
00728 {
00729 case '/':
00730 closePreviousToken( &root, ¤t, type, token );
00731
00732 if( len < expression.length()-1 && expression[len+1] == '/' )
00733 {
00734
00735 type = XTDoubleSlash;
00736 ++len;
00737 }
00738
00739
00740
00741
00742
00743 break;
00744 case ']':
00745 closePreviousToken( &root, ¤t, type, token );
00746 ++len;
00747 return root;
00748 case '[':
00749 {
00750 closePreviousToken( &root, ¤t, type, token );
00751 Tag *t = parse( expression, ++len, XTRightBracket );
00752 if( !addPredicate( &root, ¤t, t ) )
00753 delete t;
00754 break;
00755 }
00756 case '(':
00757 {
00758 closePreviousToken( &root, ¤t, type, token );
00759 Tag *t = parse( expression, ++len, XTRightParenthesis );
00760 if( current )
00761 {
00762
00763 t->addAttribute( "argument", "true" );
00764 current->addChild( t );
00765 }
00766 else
00767 {
00768 root = t;
00769
00770 }
00771 break;
00772 }
00773 case ')':
00774 closePreviousToken( &root, ¤t, type, token );
00775 ++len;
00776 return root;
00777 case '\'':
00778 if( type == XTLiteralInside )
00779 if( expression[len - 2] == '\\' )
00780 token[token.length() - 2] = c;
00781 else
00782 type = XTLiteral;
00783 else
00784 type = XTLiteralInside;
00785 break;
00786 case '@':
00787 type = XTAttribute;
00788 break;
00789 case '.':
00790 token += c;
00791 if( token.size() == 1 )
00792 {
00793 if( len < expression.length()-1 && expression[len+1] == '.' )
00794 {
00795 type = XTDoubleDot;
00796 ++len;
00797 token += c;
00798 }
00799 else
00800 {
00801 type = XTDot;
00802 }
00803 }
00804 break;
00805 case '*':
00806
00807
00808
00809
00810
00811
00812 addToken( &root, ¤t, type, "*" );
00813 type = XTElement;
00814 break;
00815 case '+':
00816 case '>':
00817 case '<':
00818 case '=':
00819 case '|':
00820 {
00821 closePreviousToken( &root, ¤t, type, token );
00822 std::string s( 1, c );
00823 Tag::TokenType ttype = getType( s );
00824 if( ttype <= border )
00825 return root;
00826 Tag *t = parse( expression, ++len, ttype );
00827 addOperator( &root, ¤t, t, ttype, s );
00828 if( border == XTRightBracket )
00829 return root;
00830 break;
00831 }
00832 default:
00833 token += c;
00834 }
00835 }
00836
00837 if( !token.empty() )
00838 addToken( &root, ¤t, type, token );
00839
00840
00841
00842 return root;
00843 }
00844
00845 void Tag::addToken( Tag **root, Tag **current, Tag::TokenType type,
00846 const std::string& token )
00847 {
00848 Tag *t = new Tag( token );
00849 if( t->isNumber() && !t->children().size() )
00850 type = XTInteger;
00851 t->addAttribute( "type", type );
00852
00853 if( *root )
00854 {
00855
00856 (*current)->addChild( t );
00857 *current = t;
00858 }
00859 else
00860 {
00861
00862 *current = *root = t;
00863 }
00864 }
00865
00866 void Tag::addOperator( Tag **root, Tag **current, Tag *arg,
00867 Tag::TokenType type, const std::string& token )
00868 {
00869 Tag *t = new Tag( token );
00870 t->addAttribute( "type", type );
00871
00872
00873 t->addAttribute( "operator", "true" );
00874 t->addChild( *root );
00875 t->addChild( arg );
00876 *current = *root = t;
00877 }
00878
00879 bool Tag::addPredicate( Tag **root, Tag **current, Tag *token )
00880 {
00881 if( !*root || !*current )
00882 return false;
00883
00884 if( ( token->isNumber() && !token->children().size() ) || token->name() == "+" )
00885 {
00886
00887 if( !token->hasAttribute( "operator", "true" ) )
00888 {
00889 token->addAttribute( "type", XTInteger );
00890 }
00891 if( *root == *current )
00892 {
00893 *root = token;
00894
00895 }
00896 else
00897 {
00898 (*root)->removeChild( *current );
00899 (*root)->addChild( token );
00900
00901 }
00902 token->addChild( *current );
00903
00904 }
00905 else
00906 {
00907 token->addAttribute( "predicate", "true" );
00908 (*current)->addChild( token );
00909 }
00910
00911 return true;
00912 }
00913
00914 Tag::TokenType Tag::getType( const std::string& c )
00915 {
00916 if( c == "|" )
00917 return XTUnion;
00918 if( c == "<" )
00919 return XTOperatorLt;
00920 if( c == ">" )
00921 return XTOperatorGt;
00922 if( c == "*" )
00923 return XTOperatorMul;
00924 if( c == "+" )
00925 return XTOperatorPlus;
00926 if( c == "=" )
00927 return XTOperatorEq;
00928
00929 return XTNone;
00930 }
00931
00932 bool Tag::isWhitespace( const char c )
00933 {
00934 return ( c == 0x09 || c == 0x0a || c == 0x0d || c == 0x20 );
00935 }
00936
00937 bool Tag::isNumber()
00938 {
00939 if( m_name.empty() )
00940 return false;
00941
00942 std::string::size_type l = m_name.length();
00943 std::string::size_type i = 0;
00944 while( i < l && isdigit( m_name[i] ) )
00945 ++i;
00946 return i == l;
00947 }
00948
00949 void Tag::add( Tag::TagList& one, const Tag::TagList& two )
00950 {
00951 Tag::TagList::const_iterator it = two.begin();
00952 for( ; it != two.end(); ++it )
00953 if( std::find( one.begin(), one.end(), (*it) ) == one.end() )
00954 one.push_back( (*it) );
00955 }
00956
00957 }