KDECore
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_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
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 case 7:
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:
00279 case 8:
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:
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:
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.begin();
00448 QList<QVariant>::ConstIterator end = c2.seq.end();
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.begin();
00464 QList<QVariant>::ConstIterator end = c2.seq.end();
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
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
00587 if ( !_context->initMaxima( m_strId ) )
00588 return false;
00589
00590
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
00615 if ( !_tree )
00616 return 1;
00617
00618 QMap<QString,PreferencesMaxima> maxima;
00619 ParseContext c( _service, _list, maxima );
00620
00621
00622 if ( !_tree->eval( &c ) )
00623 return -1;
00624
00625
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
00635 QVariant prop = service->property( _prop );
00636 if ( !prop.isValid() )
00637 return false;
00638
00639
00640 if ( prop.type() != QVariant::Int && prop.type() != QVariant::Double )
00641 return false;
00642
00643
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
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
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
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
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
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
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
00697 maxima.insert( _prop, extrema );
00698
00699
00700 return ( extrema.type == PreferencesMaxima::PM_DOUBLE ||
00701 extrema.type == PreferencesMaxima::PM_INT );
00702 }
00703
00704 }