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