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

KDECore

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_p.h"
00021 
00022 namespace KTraderParse {
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   case 7: /* EQI */
00248     if ( c1.type != c2.type )
00249     {
00250       _context->b = false;
00251       return true;
00252     }
00253     if ( c1.type == ParseContext::T_STRING )
00254     {
00255       if (m_cmd == 7) {
00256           _context->b = QString::compare(c1.str, c2.str, Qt::CaseInsensitive) == 0;
00257       } else {
00258           _context->b = ( c1.str == c2.str );
00259       }
00260       return true;
00261     }
00262     if ( c1.type == ParseContext::T_BOOL )
00263     {
00264       _context->b = ( c1.b == c2.b );
00265       return true;
00266     }
00267     if ( c1.type == ParseContext::T_DOUBLE )
00268     {
00269       _context->b = ( c1.f == c2.f );
00270       return true;
00271     }
00272     if ( c1.type == ParseContext::T_NUM )
00273     {
00274       _context->b = ( c1.i == c2.i );
00275       return true;
00276     }
00277     break;
00278   case 2: /* NEQ */
00279   case 8: /* NEQI */
00280     if ( c1.type != c2.type )
00281     {
00282       _context->b = true;
00283       return true;
00284     }
00285     if ( c1.type == ParseContext::T_STRING ) {
00286         if (m_cmd == 8) {
00287             _context->b = QString::compare(c1.str, c2.str, Qt::CaseInsensitive) != 0;
00288         } else  {
00289             _context->b = ( c1.str != c2.str );
00290         }
00291         return true;
00292     }
00293     if ( c1.type == ParseContext::T_BOOL )
00294     {
00295       _context->b = ( c1.b != c2.b );
00296       return true;
00297     }
00298     if ( c1.type == ParseContext::T_DOUBLE )
00299     {
00300       _context->b = ( c1.f != c2.f );
00301       return true;
00302     }
00303     if ( c1.type == ParseContext::T_NUM )
00304     {
00305       _context->b = ( c1.i != c2.i );
00306       return true;
00307     }
00308     break;
00309   case 3: /* GEQ */
00310     if ( c1.type != c2.type )
00311     {
00312       _context->b = false;
00313       return true;
00314     }
00315     if ( c1.type == ParseContext::T_DOUBLE )
00316     {
00317       _context->b = ( c1.f >= c2.f );
00318       return true;
00319     }
00320     if ( c1.type == ParseContext::T_NUM )
00321     {
00322       _context->b = ( c1.i >= c2.i );
00323       return true;
00324     }
00325     _context->b = false;
00326     return true;
00327 
00328   case 4: /* LEQ */
00329     if ( c1.type != c2.type )
00330     {
00331       _context->b = false;
00332       return true;
00333     }
00334     if ( c1.type == ParseContext::T_DOUBLE )
00335     {
00336       _context->b = ( c1.f <= c2.f );
00337       return true;
00338     }
00339     if ( c1.type == ParseContext::T_NUM )
00340     {
00341       _context->b = ( c1.i <= c2.i );
00342       return true;
00343     }
00344     _context->b = false;
00345     return true;
00346 
00347   case 5: /* < */
00348     if ( c1.type != c2.type )
00349     {
00350       _context->b = false;
00351       return true;
00352     }
00353     if ( c1.type == ParseContext::T_DOUBLE )
00354     {
00355       _context->b = ( c1.f < c2.f );
00356       return true;
00357     }
00358     if ( c1.type == ParseContext::T_NUM )
00359     {
00360       _context->b = ( c1.i < c2.i );
00361       return true;
00362     }
00363     _context->b = false;
00364     return true;
00365 
00366   case 6: /* > */
00367     if ( c1.type != c2.type )
00368     {
00369       _context->b = false;
00370       return true;
00371     }
00372     if ( c1.type == ParseContext::T_DOUBLE )
00373     {
00374       _context->b = ( c1.f > c2.f );
00375       return true;
00376     }
00377     if ( c1.type == ParseContext::T_NUM )
00378     {
00379       _context->b = ( c1.i > c2.i );
00380       return true;
00381     }
00382     _context->b = false;
00383     return true;
00384 
00385   }
00386 
00387   return false;
00388 }
00389 
00390 bool ParseTreeNOT::eval( ParseContext *_context ) const
00391 {
00392   ParseContext c1( _context );
00393   if ( !m_pLeft->eval( &c1 ) )
00394     return false;
00395   if ( c1.type != ParseContext::T_BOOL )
00396     return false;
00397 
00398   _context->b = !c1.b;
00399   _context->type = ParseContext::T_BOOL;
00400 
00401   return true;
00402 }
00403 
00404 bool ParseTreeEXIST::eval( ParseContext *_context ) const
00405 {
00406   _context->type = ParseContext::T_BOOL;
00407 
00408   QVariant prop = _context->service->property( m_id );
00409   _context->b = prop.isValid();
00410 
00411   return true;
00412 }
00413 
00414 bool ParseTreeMATCH::eval( ParseContext *_context ) const
00415 {
00416   _context->type = ParseContext::T_BOOL;
00417 
00418   ParseContext c1( _context );
00419   ParseContext c2( _context );
00420   if ( !m_pLeft->eval( &c1 ) )
00421     return false;
00422   if ( !m_pRight->eval( &c2 ) )
00423     return false;
00424   if ( c1.type != ParseContext::T_STRING || c2.type != ParseContext::T_STRING )
00425     return false;
00426 
00427   _context->b = c2.str.contains( c1.str, m_cs );
00428 
00429   return true;
00430 }
00431 
00432 bool ParseTreeIN::eval( ParseContext *_context ) const
00433 {
00434   _context->type = ParseContext::T_BOOL;
00435 
00436   ParseContext c1( _context );
00437   ParseContext c2( _context );
00438   if ( !m_pLeft->eval( &c1 ) )
00439     return false;
00440   if ( !m_pRight->eval( &c2 ) )
00441     return false;
00442 
00443   if ( (c1.type == ParseContext::T_NUM) &&
00444        (c2.type == ParseContext::T_SEQ) &&
00445        ((*(c2.seq.begin())).type() == QVariant::Int)) {
00446 
00447       QList<QVariant>::ConstIterator it = c2.seq.constBegin();
00448       QList<QVariant>::ConstIterator end = c2.seq.constEnd();
00449       _context->b = false;
00450       for (; it != end; ++it)
00451       if ((*it).type() == QVariant::Int &&
00452           (*it).toInt() == c1.i) {
00453           _context->b = true;
00454           break;
00455       }
00456       return true;
00457   }
00458 
00459   if ( c1.type == ParseContext::T_DOUBLE &&
00460        c2.type == ParseContext::T_SEQ &&
00461        (*(c2.seq.begin())).type() == QVariant::Double) {
00462 
00463       QList<QVariant>::ConstIterator it = c2.seq.constBegin();
00464       QList<QVariant>::ConstIterator end = c2.seq.constEnd();
00465       _context->b = false;
00466       for (; it != end; ++it)
00467       if ((*it).type() == QVariant::Double &&
00468           (*it).toDouble() == c1.i) {
00469           _context->b = true;
00470           break;
00471       }
00472       return true;
00473   }
00474 
00475   if (c1.type == ParseContext::T_STRING && c2.type == ParseContext::T_STR_SEQ)
00476   {
00477       if (false && m_substring) {
00478           _context->b = false;
00479           foreach (const QString &string, c2.strSeq) {
00480               if (string.contains(c1.str, m_cs)) {
00481                   _context->b = true;
00482                   break;
00483               }
00484           }
00485       } else {
00486           _context->b = c2.strSeq.contains(c1.str, m_cs);
00487       }
00488 
00489       return true;
00490   }
00491 
00492   return false;
00493 }
00494 
00495 bool ParseTreeID::eval( ParseContext *_context ) const
00496 {
00497   QVariant prop = _context->service->property( m_str );
00498   if ( !prop.isValid() )
00499     return false;
00500 
00501   if ( prop.type() == QVariant::String )
00502   {
00503     _context->str = prop.toString();
00504     _context->type = ParseContext::T_STRING;
00505     return true;
00506   }
00507 
00508   if ( prop.type() == QVariant::Int )
00509   {
00510     _context->i = prop.toInt();
00511     _context->type = ParseContext::T_NUM;
00512     return true;
00513   }
00514 
00515   if ( prop.type() == QVariant::Bool )
00516   {
00517     _context->b = prop.toBool();
00518     _context->type = ParseContext::T_BOOL;
00519     return true;
00520   }
00521 
00522   if ( prop.type() == QVariant::Double )
00523   {
00524     _context->f = prop.toDouble();
00525     _context->type = ParseContext::T_DOUBLE;
00526     return true;
00527   }
00528 
00529   if ( prop.type() == QVariant::List )
00530   {
00531     _context->seq = prop.toList();
00532     _context->type = ParseContext::T_SEQ;
00533     return true;
00534   }
00535 
00536   if ( prop.type() == QVariant::StringList )
00537   {
00538     _context->strSeq = prop.toStringList();
00539     _context->type = ParseContext::T_STR_SEQ;
00540     return true;
00541   }
00542 
00543   // Value has unknown type
00544   return false;
00545 }
00546 
00547 bool ParseTreeMIN2::eval( ParseContext *_context ) const
00548 {
00549   _context->type = ParseContext::T_DOUBLE;
00550 
00551   QVariant prop = _context->service->property( m_strId );
00552   if ( !prop.isValid() )
00553     return false;
00554 
00555   if ( !_context->initMaxima( m_strId ) )
00556     return false;
00557 
00558   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
00559   if ( it == _context->maxima.end() )
00560     return false;
00561 
00562   if ( prop.type() == QVariant::Int && it.value().type == PreferencesMaxima::PM_INT )
00563   {
00564     _context->f = (double)( prop.toInt() - it.value().iMin ) /
00565                   (double)(it.value().iMax - it.value().iMin ) * (-2.0) + 1.0;
00566     return true;
00567   }
00568   else if ( prop.type() == QVariant::Double && it.value().type == PreferencesMaxima::PM_DOUBLE )
00569   {
00570     _context->f = ( prop.toDouble() - it.value().fMin ) / (it.value().fMax - it.value().fMin )
00571                   * (-2.0) + 1.0;
00572     return true;
00573   }
00574 
00575   return false;
00576 }
00577 
00578 bool ParseTreeMAX2::eval( ParseContext *_context ) const
00579 {
00580   _context->type = ParseContext::T_DOUBLE;
00581 
00582   QVariant prop = _context->service->property( m_strId );
00583   if ( !prop.isValid() )
00584     return false;
00585 
00586   // Create extrema
00587   if ( !_context->initMaxima( m_strId ) )
00588     return false;
00589 
00590   // Find extrema
00591   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
00592   if ( it == _context->maxima.end() )
00593     return false;
00594 
00595   if ( prop.type() == QVariant::Int && it.value().type == PreferencesMaxima::PM_INT )
00596   {
00597     _context->f = (double)( prop.toInt() - it.value().iMin ) /
00598                   (double)(it.value().iMax - it.value().iMin ) * 2.0 - 1.0;
00599     return true;
00600   }
00601   else if ( prop.type() == QVariant::Double && it.value().type == PreferencesMaxima::PM_DOUBLE )
00602   {
00603     _context->f = ( prop.toDouble() - it.value().fMin ) /
00604                   (it.value().fMax - it.value().fMin ) * 2.0 - 1.0;
00605     return true;
00606   }
00607 
00608   return false;
00609 }
00610 
00611 int matchConstraint( const ParseTreeBase *_tree, const KService::Ptr &_service,
00612              const KService::List& _list )
00613 {
00614   // Empty tree matches always
00615   if ( !_tree )
00616     return 1;
00617 
00618   QMap<QString,PreferencesMaxima> maxima;
00619   ParseContext c( _service, _list, maxima );
00620 
00621   // Error during evaluation ?
00622   if ( !_tree->eval( &c ) )
00623     return -1;
00624 
00625   // Did we get a bool ?
00626   if ( c.type != ParseContext::T_BOOL )
00627     return -1;
00628 
00629   return ( c.b ? 1 : 0 );
00630 }
00631 
00632 bool ParseContext::initMaxima( const QString& _prop )
00633 {
00634   // Is the property known ?
00635   QVariant prop = service->property( _prop );
00636   if ( !prop.isValid() )
00637     return false;
00638 
00639   // Numeric ?
00640   if ( prop.type() != QVariant::Int && prop.type() != QVariant::Double )
00641     return false;
00642 
00643   // Did we cache the result ?
00644   QMap<QString,PreferencesMaxima>::Iterator it = maxima.find( _prop );
00645   if ( it != maxima.end() )
00646     return ( it.value().type == PreferencesMaxima::PM_DOUBLE ||
00647          it.value().type == PreferencesMaxima::PM_INT );
00648 
00649   // Double or Int ?
00650   PreferencesMaxima extrema;
00651   if ( prop.type() == QVariant::Int )
00652     extrema.type = PreferencesMaxima::PM_INVALID_INT;
00653   else
00654     extrema.type = PreferencesMaxima::PM_INVALID_DOUBLE;
00655 
00656   // Iterate over all offers
00657   KService::List::ConstIterator oit = offers.begin();
00658   for( ; oit != offers.end(); ++oit )
00659   {
00660     QVariant p = (*oit)->property( _prop );
00661     if ( p.isValid() )
00662     {
00663       // Determine new maximum/minimum
00664       if ( extrema.type == PreferencesMaxima::PM_INVALID_INT )
00665       {
00666     extrema.type = PreferencesMaxima::PM_INT;
00667     extrema.iMin = p.toInt();
00668     extrema.iMax = p.toInt();
00669       }
00670       // Correct existing extrema
00671       else if ( extrema.type == PreferencesMaxima::PM_INT )
00672       {
00673     if ( p.toInt() < extrema.iMin )
00674       extrema.iMin = p.toInt();
00675     if ( p.toInt() > extrema.iMax )
00676       extrema.iMax = p.toInt();
00677       }
00678       // Determine new maximum/minimum
00679       else if ( extrema.type == PreferencesMaxima::PM_INVALID_DOUBLE )
00680       {
00681     extrema.type = PreferencesMaxima::PM_DOUBLE;
00682     extrema.fMin = p.toDouble();
00683     extrema.fMax = p.toDouble();
00684       }
00685       // Correct existing extrema
00686       else if ( extrema.type == PreferencesMaxima::PM_DOUBLE )
00687       {
00688     if ( p.toDouble() < it.value().fMin )
00689       extrema.fMin = p.toDouble();
00690     if ( p.toDouble() > it.value().fMax )
00691       extrema.fMax = p.toDouble();
00692       }
00693     }
00694   }
00695 
00696   // Cache the result
00697   maxima.insert( _prop, extrema );
00698 
00699   // Did we succeed ?
00700   return ( extrema.type == PreferencesMaxima::PM_DOUBLE ||
00701        extrema.type == PreferencesMaxima::PM_INT );
00702 }
00703 
00704 }

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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