• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

ktraderparsetree.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "ktraderparsetree.h"
00021 
00022 namespace KIO {
00023 
00024 bool ParseTreeOR::eval( ParseContext *_context ) const
00025 {
00026   ParseContext c1( _context );
00027   ParseContext c2( _context );
00028 
00029 // don't evaluate both expressions but return immediately
00030 // if the first one of them succeeds. Otherwise queries like
00031 // ((not exist Blah) or (Blah == 'Foo')) do not work, because
00032 // the evaluation of the second term ends up in a fatal error
00033 // (Simon)
00034 
00035   if ( !m_pLeft->eval( &c1 ) )
00036     return false;
00037 
00038   if ( c1.type != ParseContext::T_BOOL )
00039     return false;
00040 
00041   _context->b = c1.b;
00042   _context->type = ParseContext::T_BOOL;  
00043   if ( c1.b )
00044     return true;
00045 
00046   if ( !m_pRight->eval( &c2 ) )
00047     return false;
00048 
00049   if ( c2.type != ParseContext::T_BOOL )
00050     return false;
00051 
00052   _context->b = ( c1.b || c2.b );
00053   _context->type = ParseContext::T_BOOL;
00054 
00055   return true;
00056 }
00057 
00058 bool ParseTreeAND::eval( ParseContext *_context ) const
00059 {
00060   _context->type = ParseContext::T_BOOL;
00061 
00062   ParseContext c1( _context );
00063   ParseContext c2( _context );
00064   if ( !m_pLeft->eval( &c1 ) )
00065     return false;
00066   if ( c1.type != ParseContext::T_BOOL )
00067     return false;
00068   if ( !c1.b )
00069   {
00070     _context->b = false;
00071     return true;
00072   }
00073 
00074   if ( !m_pRight->eval( &c2 ) )
00075     return false;
00076   if ( c2.type != ParseContext::T_BOOL )
00077     return false;
00078 
00079   _context->b = ( c1.b && c2.b );
00080 
00081   return true;
00082 }
00083 
00084 bool ParseTreeCALC::eval( ParseContext *_context ) const
00085 {
00086   ParseContext c1( _context );
00087   ParseContext c2( _context );
00088   if ( !m_pLeft->eval( &c1 ) )
00089     return false;
00090   if ( !m_pRight->eval( &c2 ) )
00091     return false;
00092 
00093   // Bool extension
00094   if ( c1.type != ParseContext::T_NUM && c1.type != ParseContext::T_DOUBLE && c1.type != ParseContext::T_BOOL )
00095     return false;
00096   // Bool extension
00097   if ( c2.type != ParseContext::T_NUM && c2.type != ParseContext::T_DOUBLE && c2.type != ParseContext::T_BOOL )
00098     return false;
00099   // Bool extension
00100   if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_BOOL )
00101     return false;
00102 
00106   if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_DOUBLE )
00107   {
00108     c1.type = ParseContext::T_DOUBLE;
00109     c1.f = (double)c1.i;
00110   }
00111   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_NUM )
00112   {
00113     c2.type = ParseContext::T_DOUBLE;
00114     c2.f = (double)c2.i;
00115   }
00116   // Bool extension
00117   else if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_NUM )
00118   {
00119     c1.type = ParseContext::T_NUM;
00120     if ( c1.b )
00121       c1.i = 1;
00122     else
00123       c1.i = -1;
00124   }
00125   // Bool extension
00126   else if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_DOUBLE )
00127   {
00128     c1.type = ParseContext::T_DOUBLE;
00129     if ( c1.b )
00130       c1.f = 1.0;
00131     else
00132       c1.f = -1.0;
00133   }
00134   // Bool extension
00135   else if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_BOOL )
00136   {
00137     c2.type = ParseContext::T_NUM;
00138     if ( c2.b )
00139       c2.i = 1;
00140     else
00141       c2.i = -1;
00142   }
00143   // Bool extension
00144   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_BOOL )
00145   {
00146     c2.type = ParseContext::T_DOUBLE;
00147     if ( c2.b )
00148       c2.f = 1.0;
00149     else
00150       c2.f = -1.0;
00151   }
00152 
00153   _context->type = c1.type;
00154 
00158   switch( m_cmd )
00159   {
00160   case 1: /* Add */
00161     if ( c1.type == ParseContext::T_DOUBLE )
00162     {
00163       _context->f = ( c1.f + c2.f );
00164       return true;
00165     }
00166     if ( c1.type == ParseContext::T_NUM )
00167     {
00168       _context->i = ( c1.i + c2.i );
00169       return true;
00170     }
00171     break;
00172   case 2: /* Sub */
00173     if ( c1.type == ParseContext::T_DOUBLE )
00174     {
00175       _context->f = ( c1.f - c2.f );
00176       return true;
00177     }
00178     if ( c1.type == ParseContext::T_NUM )
00179     {
00180       _context->i = ( c1.i - c2.i );
00181       return true;
00182     }
00183     break;
00184   case 3: /* Mul */
00185     if ( c1.type == ParseContext::T_DOUBLE )
00186     {
00187       //cout << "Double Mult" << endl;
00188       _context->f = ( c1.f * c2.f );
00189       return true;
00190     }
00191     if ( c1.type == ParseContext::T_NUM )
00192     {
00193       _context->i = ( c1.i * c2.i );
00194       return true;
00195     }
00196     break;
00197   case 4: /* Div */
00198     if ( c1.type == ParseContext::T_DOUBLE )
00199     {
00200       _context->f = ( c1.f / c2.f );
00201       return true;
00202     }
00203     if ( c1.type == ParseContext::T_NUM )
00204     {
00205       _context->i = ( c1.i / c2.i );
00206       return true;
00207     }
00208     break;
00209   }
00210 
00211   return false;
00212 }
00213 
00214 bool ParseTreeCMP::eval( ParseContext *_context ) const
00215 {
00216   //cout << "CMP 1 cmd=" << m_cmd << endl;
00217   ParseContext c1( _context );
00218   ParseContext c2( _context );
00219   if ( !m_pLeft->eval( &c1 ) )
00220     return false;
00221 
00222   if ( !m_pRight->eval( &c2 ) )
00223     return false;
00224 
00228   if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_DOUBLE )
00229   {
00230     c1.type = ParseContext::T_DOUBLE;
00231     c1.f = (double)c1.i;
00232   }
00233   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_NUM )
00234   {
00235     c2.type = ParseContext::T_DOUBLE;
00236     c2.f = (double)c2.i;
00237   }
00238 
00242   _context->type = ParseContext::T_BOOL;
00243 
00244   switch( m_cmd )
00245   {
00246   case 1: /* EQ */
00247     if ( c1.type != c2.type )
00248     {
00249       _context->b = false;
00250       return true;
00251     }
00252     if ( c1.type == ParseContext::T_STRING )
00253     {
00254       _context->b = ( c1.str == c2.str );
00255       return true;
00256     }
00257     if ( c1.type == ParseContext::T_BOOL )
00258     {
00259       _context->b = ( c1.b == c2.b );
00260       return true;
00261     }
00262     if ( c1.type == ParseContext::T_DOUBLE )
00263     {
00264       _context->b = ( c1.f == c2.f );
00265       return true;
00266     }
00267     if ( c1.type == ParseContext::T_NUM )
00268     {
00269       _context->b = ( c1.i == c2.i );
00270       return true;
00271     }
00272     break;
00273   case 2: /* NEQ */
00274     if ( c1.type != c2.type )
00275     {
00276       _context->b = true;
00277       return true;
00278     }
00279     if ( c1.type == ParseContext::T_STRING )
00280     {
00281       _context->b = ( c1.str != c2.str );
00282       return true;
00283     }
00284     if ( c1.type == ParseContext::T_BOOL )
00285     {
00286       _context->b = ( c1.b != c2.b );
00287       return true;
00288     }
00289     if ( c1.type == ParseContext::T_DOUBLE )
00290     {
00291       _context->b = ( c1.f != c2.f );
00292       return true;
00293     }
00294     if ( c1.type == ParseContext::T_NUM )
00295     {
00296       _context->b = ( c1.i != c2.i );
00297       return true;
00298     }
00299     break;
00300   case 3: /* GEQ */
00301     if ( c1.type != c2.type )
00302     {
00303       _context->b = false;
00304       return true;
00305     }
00306     if ( c1.type == ParseContext::T_DOUBLE )
00307     {
00308       _context->b = ( c1.f >= c2.f );
00309       return true;
00310     }
00311     if ( c1.type == ParseContext::T_NUM )
00312     {
00313       _context->b = ( c1.i >= c2.i );
00314       return true;
00315     }
00316     _context->b = false;
00317     return true;
00318 
00319   case 4: /* LEQ */
00320     if ( c1.type != c2.type )
00321     {
00322       _context->b = false;
00323       return true;
00324     }
00325     if ( c1.type == ParseContext::T_DOUBLE )
00326     {
00327       _context->b = ( c1.f <= c2.f );
00328       return true;
00329     }
00330     if ( c1.type == ParseContext::T_NUM )
00331     {
00332       _context->b = ( c1.i <= c2.i );
00333       return true;
00334     }
00335     _context->b = false;
00336     return true;
00337 
00338   case 5: /* < */
00339     if ( c1.type != c2.type )
00340     {
00341       _context->b = false;
00342       return true;
00343     }
00344     if ( c1.type == ParseContext::T_DOUBLE )
00345     {
00346       _context->b = ( c1.f < c2.f );
00347       return true;
00348     }
00349     if ( c1.type == ParseContext::T_NUM )
00350     {
00351       _context->b = ( c1.i < c2.i );
00352       return true;
00353     }
00354     _context->b = false;
00355     return true;
00356 
00357   case 6: /* > */
00358     if ( c1.type != c2.type )
00359     {
00360       _context->b = false;
00361       return true;
00362     }
00363     if ( c1.type == ParseContext::T_DOUBLE )
00364     {
00365       _context->b = ( c1.f > c2.f );
00366       return true;
00367     }
00368     if ( c1.type == ParseContext::T_NUM )
00369     {
00370       _context->b = ( c1.i > c2.i );
00371       return true;
00372     }
00373     _context->b = false;
00374     return true;
00375 
00376   }
00377 
00378   return false;
00379 }
00380 
00381 bool ParseTreeNOT::eval( ParseContext *_context ) const
00382 {
00383   ParseContext c1( _context );
00384   if ( !m_pLeft->eval( &c1 ) )
00385     return false;
00386   if ( c1.type != ParseContext::T_BOOL )
00387     return false;
00388 
00389   _context->b = !c1.b;
00390   _context->type = ParseContext::T_BOOL;
00391 
00392   return true;
00393 }
00394 
00395 bool ParseTreeEXIST::eval( ParseContext *_context ) const
00396 {
00397   _context->type = ParseContext::T_BOOL;
00398 
00399   QVariant prop = _context->service->property( m_id );
00400   _context->b = prop.isValid();
00401 
00402   return true;
00403 }
00404 
00405 bool ParseTreeMATCH::eval( ParseContext *_context ) const
00406 {
00407   _context->type = ParseContext::T_BOOL;
00408 
00409   ParseContext c1( _context );
00410   ParseContext c2( _context );
00411   if ( !m_pLeft->eval( &c1 ) )
00412     return false;
00413   if ( !m_pRight->eval( &c2 ) )
00414     return false;
00415   if ( c1.type != ParseContext::T_STRING || c2.type != ParseContext::T_STRING )
00416     return false;
00417 
00418   _context->b = ( c2.str.find( c1.str ) != -1 );
00419 
00420   return true;
00421 }
00422 
00423 bool ParseTreeIN::eval( ParseContext *_context ) const
00424 {
00425   _context->type = ParseContext::T_BOOL;
00426 
00427   ParseContext c1( _context );
00428   ParseContext c2( _context );
00429   if ( !m_pLeft->eval( &c1 ) )
00430     return false;
00431   if ( !m_pRight->eval( &c2 ) )
00432     return false;
00433 
00434   if ( (c1.type == ParseContext::T_NUM) &&
00435        (c2.type == ParseContext::T_SEQ) &&
00436        ((*(c2.seq.begin())).type() == QVariant::Int)) {
00437 
00438       QValueList<QVariant>::ConstIterator it = c2.seq.begin();
00439       QValueList<QVariant>::ConstIterator end = c2.seq.end();
00440       _context->b = false;
00441       for (; it != end; it++)
00442       if ((*it).type() == QVariant::Int &&
00443           (*it).toInt() == c1.i) {
00444           _context->b = true;
00445           break;
00446       }
00447       return true;
00448   }
00449 
00450   if ( c1.type == ParseContext::T_DOUBLE &&
00451        c2.type == ParseContext::T_SEQ &&
00452        (*(c2.seq.begin())).type() == QVariant::Double) {
00453 
00454       QValueList<QVariant>::ConstIterator it = c2.seq.begin();
00455       QValueList<QVariant>::ConstIterator end = c2.seq.end();
00456       _context->b = false;
00457       for (; it != end; it++)
00458       if ((*it).type() == QVariant::Double &&
00459           (*it).toDouble() == c1.i) {
00460           _context->b = true;
00461           break;
00462       }
00463       return true;
00464   }
00465 
00466   if ( c1.type == ParseContext::T_STRING && c2.type == ParseContext::T_STR_SEQ )
00467   {
00468     _context->b = ( c2.strSeq.find( c1.str ) != c2.strSeq.end() );
00469     return true;
00470   }
00471 
00472   return false;
00473 }
00474 
00475 bool ParseTreeID::eval( ParseContext *_context ) const
00476 {
00477   QVariant prop = _context->service->property( m_str );
00478   if ( !prop.isValid() )
00479     return false;
00480 
00481   if ( prop.type() == QVariant::String )
00482   {
00483     _context->str = prop.toString();
00484     _context->type = ParseContext::T_STRING;
00485     return true;
00486   }
00487 
00488   if ( prop.type() == QVariant::Int )
00489   {
00490     _context->i = prop.toInt();
00491     _context->type = ParseContext::T_NUM;
00492     return true;
00493   }
00494 
00495   if ( prop.type() == QVariant::Bool )
00496   {
00497     _context->b = prop.toBool();
00498     _context->type = ParseContext::T_BOOL;
00499     return true;
00500   }
00501 
00502   if ( prop.type() == QVariant::Double )
00503   {
00504     _context->f = prop.toDouble();
00505     _context->type = ParseContext::T_DOUBLE;
00506     return true;
00507   }
00508 
00509   if ( prop.type() == QVariant::List )
00510   {
00511     _context->seq = prop.toList();
00512     _context->type = ParseContext::T_SEQ;
00513     return true;
00514   }
00515 
00516   if ( prop.type() == QVariant::StringList )
00517   {
00518     _context->strSeq = prop.toStringList();
00519     _context->type = ParseContext::T_STR_SEQ;
00520     return true;
00521   }
00522 
00523   // Value has unknown type
00524   return false;
00525 }
00526 
00527 bool ParseTreeMIN2::eval( ParseContext *_context ) const
00528 {
00529   _context->type = ParseContext::T_DOUBLE;
00530 
00531   QVariant prop = _context->service->property( m_strId );
00532   if ( !prop.isValid() )
00533     return false;
00534 
00535   if ( !_context->initMaxima( m_strId ) )
00536     return false;
00537 
00538   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
00539   if ( it == _context->maxima.end() )
00540     return false;
00541 
00542   if ( prop.type() == QVariant::Int && it.data().type == PreferencesMaxima::PM_INT )
00543   {
00544     _context->f = (double)( prop.toInt() - it.data().iMin ) /
00545                   (double)(it.data().iMax - it.data().iMin ) * (-2.0) + 1.0;
00546     return true;
00547   }
00548   else if ( prop.type() == QVariant::Double && it.data().type == PreferencesMaxima::PM_DOUBLE )
00549   {
00550     _context->f = ( prop.toDouble() - it.data().fMin ) / (it.data().fMax - it.data().fMin )
00551                   * (-2.0) + 1.0;
00552     return true;
00553   }
00554 
00555   return false;
00556 }
00557 
00558 bool ParseTreeMAX2::eval( ParseContext *_context ) const
00559 {
00560   _context->type = ParseContext::T_DOUBLE;
00561 
00562   QVariant prop = _context->service->property( m_strId );
00563   if ( !prop.isValid() )
00564     return false;
00565 
00566   // Create extrema
00567   if ( !_context->initMaxima( m_strId ) )
00568     return false;
00569 
00570   // Find extrema
00571   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
00572   if ( it == _context->maxima.end() )
00573     return false;
00574 
00575   if ( prop.type() == QVariant::Int && it.data().type == PreferencesMaxima::PM_INT )
00576   {
00577     _context->f = (double)( prop.toInt() - it.data().iMin ) /
00578                   (double)(it.data().iMax - it.data().iMin ) * 2.0 - 1.0;
00579     return true;
00580   }
00581   else if ( prop.type() == QVariant::Double && it.data().type == PreferencesMaxima::PM_DOUBLE )
00582   {
00583     _context->f = ( prop.toDouble() - it.data().fMin ) /
00584                   (it.data().fMax - it.data().fMin ) * 2.0 - 1.0;
00585     return true;
00586   }
00587 
00588   return false;
00589 }
00590 
00591 int matchConstraint( const ParseTreeBase *_tree, const KService::Ptr &_service,
00592              const KServiceTypeProfile::OfferList& _list )
00593 {
00594   // Empty tree matches always
00595   if ( !_tree )
00596     return 1;
00597 
00598   QMap<QString,PreferencesMaxima> maxima;
00599   ParseContext c( _service, _list, maxima );
00600 
00601   // Error during evaluation ?
00602   if ( !_tree->eval( &c ) )
00603     return -1;
00604 
00605   // Did we get a bool ?
00606   if ( c.type != ParseContext::T_BOOL )
00607     return -1;
00608 
00609   return ( c.b ? 1 : 0 );
00610 }
00611 
00612 PreferencesReturn matchPreferences( const ParseTreeBase *_tree, const KService::Ptr &_service,
00613                     const KServiceTypeProfile::OfferList& _list )
00614 {
00615   // By default: error
00616   PreferencesReturn ret;
00617 
00618   if ( !_tree )
00619     return ret;
00620 
00621   QMap<QString,PreferencesMaxima> maxima;
00622   ParseContext c( _service, _list, maxima );
00623 
00624   if ( !_tree->eval( &c ) )
00625     return ret;
00626 
00627   // Did we get a numeric return value ?
00628   if ( c.type == ParseContext::T_NUM )
00629   {
00630     ret.type = PreferencesReturn::PRT_DOUBLE;
00631     ret.f = (double)c.i;
00632   }
00633   else if ( c.type == ParseContext::T_DOUBLE )
00634   {
00635     ret.type = PreferencesReturn::PRT_DOUBLE;
00636     ret.f = c.f;
00637   }
00638 
00639   return ret;
00640 }
00641 
00642 bool ParseContext::initMaxima( const QString& _prop )
00643 {
00644   // Is the property known ?
00645   QVariant prop = service->property( _prop );
00646   if ( !prop.isValid() )
00647     return false;
00648 
00649   // Numeric ?
00650   if ( prop.type() != QVariant::Int && prop.type() != QVariant::Double )
00651     return false;
00652 
00653   // Did we cache the result ?
00654   QMap<QString,PreferencesMaxima>::Iterator it = maxima.find( _prop );
00655   if ( it != maxima.end() )
00656     return ( it.data().type == PreferencesMaxima::PM_DOUBLE ||
00657          it.data().type == PreferencesMaxima::PM_INT );
00658 
00659   // Double or Int ?
00660   PreferencesMaxima extrema;
00661   if ( prop.type() == QVariant::Int )
00662     extrema.type = PreferencesMaxima::PM_INVALID_INT;
00663   else
00664     extrema.type = PreferencesMaxima::PM_INVALID_DOUBLE;
00665 
00666   // Iterate over all offers
00667   KServiceTypeProfile::OfferList::ConstIterator oit = offers.begin();
00668   for( ; oit != offers.end(); ++oit )
00669   {
00670     QVariant p = (*oit).service()->property( _prop );
00671     if ( p.isValid() )
00672     {
00673       // Determine new maximum/minimum
00674       if ( extrema.type == PreferencesMaxima::PM_INVALID_INT )
00675       {
00676     extrema.type = PreferencesMaxima::PM_INT;
00677     extrema.iMin = p.toInt();
00678     extrema.iMax = p.toInt();
00679       }
00680       // Correct existing extrema
00681       else if ( extrema.type == PreferencesMaxima::PM_INT )
00682       {
00683     if ( p.toInt() < extrema.iMin )
00684       extrema.iMin = p.toInt();
00685     if ( p.toInt() > extrema.iMax )
00686       extrema.iMax = p.toInt();
00687       }
00688       // Determine new maximum/minimum
00689       else if ( extrema.type == PreferencesMaxima::PM_INVALID_DOUBLE )
00690       {
00691     extrema.type = PreferencesMaxima::PM_DOUBLE;
00692     extrema.fMin = p.toDouble();
00693     extrema.fMax = p.toDouble();
00694       }
00695       // Correct existing extrema
00696       else if ( extrema.type == PreferencesMaxima::PM_DOUBLE )
00697       {
00698     if ( p.toDouble() < it.data().fMin )
00699       extrema.fMin = p.toDouble();
00700     if ( p.toDouble() > it.data().fMax )
00701       extrema.fMax = p.toDouble();
00702       }
00703     }
00704   }
00705 
00706   // Cache the result
00707   maxima.insert( _prop, extrema );
00708 
00709   // Did we succeed ?
00710   return ( extrema.type == PreferencesMaxima::PM_DOUBLE ||
00711        extrema.type == PreferencesMaxima::PM_INT );
00712 }
00713 
00714 }

kio

Skip menu "kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal