kio
ktraderparsetree.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00030
00031
00032
00033
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
00094 if ( c1.type != ParseContext::T_NUM && c1.type != ParseContext::T_DOUBLE && c1.type != ParseContext::T_BOOL )
00095 return false;
00096
00097 if ( c2.type != ParseContext::T_NUM && c2.type != ParseContext::T_DOUBLE && c2.type != ParseContext::T_BOOL )
00098 return false;
00099
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
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
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
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
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:
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:
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:
00185 if ( c1.type == ParseContext::T_DOUBLE )
00186 {
00187
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:
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
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:
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:
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:
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:
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
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
00567 if ( !_context->initMaxima( m_strId ) )
00568 return false;
00569
00570
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
00595 if ( !_tree )
00596 return 1;
00597
00598 QMap<QString,PreferencesMaxima> maxima;
00599 ParseContext c( _service, _list, maxima );
00600
00601
00602 if ( !_tree->eval( &c ) )
00603 return -1;
00604
00605
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
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
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
00645 QVariant prop = service->property( _prop );
00646 if ( !prop.isValid() )
00647 return false;
00648
00649
00650 if ( prop.type() != QVariant::Int && prop.type() != QVariant::Double )
00651 return false;
00652
00653
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
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
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
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
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
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
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
00707 maxima.insert( _prop, extrema );
00708
00709
00710 return ( extrema.type == PreferencesMaxima::PM_DOUBLE ||
00711 extrema.type == PreferencesMaxima::PM_INT );
00712 }
00713
00714 }