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 }