00001 #include "MercuryUtil.h"
00002 #include "PStack.h"
00003 #include "MercuryLog.h"
00004
00005 static PSElement NILElement;
00006
00007 MString PSElement::GetValueS( ) const
00008 {
00009 if ( type == STRING )
00010 return *data.dataS;
00011 else if ( type == INTEGER )
00012 return ssprintf( "%li",data.l );
00013 else if ( type == FLOAT )
00014 return ssprintf( "%f",data.f );
00015 else if ( type == BOOL )
00016 return ssprintf( "%d",data.b );
00017 else if ( type == NIL )
00018 return "NIL";
00019 else
00020 return "";
00021 }
00022
00023 bool PSElement::GetValueS( MString & ret )
00024 {
00025 if ( type == STRING )
00026 ret = *data.dataS;
00027 else if ( type == INTEGER )
00028 ret = ssprintf( "%li",data.l );
00029 else if ( type == FLOAT )
00030 ret = ssprintf( "%f",data.f );
00031 else if ( type == BOOL )
00032 ret = ssprintf( "%d",data.b );
00033 else if ( type == NIL )
00034 ret = "NIL";
00035 else
00036 return false;
00037 return true;
00038 }
00039
00040 int PSElement::GetValueI( ) const
00041 {
00042 if ( type == INTEGER || type == PARAMETER )
00043 return data.l;
00044 else if ( type == FLOAT )
00045 return int(data.f);
00046 else if ( type == BOOL )
00047 return data.b;
00048 else if ( type == STRING )
00049 return atoi( data.dataS->c_str() );
00050 else
00051 return 0;
00052 }
00053
00054 bool PSElement::GetValueI( long &ret )
00055 {
00056 if ( type == INTEGER || type == PARAMETER )
00057 {
00058 ret = data.l;
00059 return true;
00060 }
00061 else if ( type == FLOAT )
00062 {
00063 ret = type;
00064 return true;
00065 }
00066 else if ( type == BOOL )
00067 {
00068 ret = data.b;
00069 return true;
00070 }
00071 return false;
00072 }
00073
00074 float PSElement::GetValueF( ) const
00075 {
00076 if ( type == INTEGER )
00077 return float(data.l);
00078 else if ( type == FLOAT )
00079 return data.f;
00080 else if ( type == STRING )
00081 return float(atof(data.dataS->c_str()));
00082 else
00083 return 0;
00084 }
00085
00086 bool PSElement::GetValueF( float & ret )
00087 {
00088 if ( type == INTEGER )
00089 {
00090 ret = float(data.l);
00091 return true;
00092 }
00093 else if ( type == FLOAT )
00094 {
00095 ret = data.f;
00096 return true;
00097 }
00098 else if ( type == STRING )
00099 {
00100 ret = float(atof(data.dataS->c_str()));
00101 return true;
00102 }
00103 else
00104 return false;
00105 }
00106
00107 bool PSElement::GetValueB( ) const
00108 {
00109 if ( type == BOOL )
00110 return data.b;
00111 if ( type == INTEGER )
00112 return data.l!=0;
00113 else if ( type == FLOAT )
00114 return data.f!=0;
00115 else
00116 return 0;
00117 }
00118
00119 bool PSElement::GetValueB( bool & ret )
00120 {
00121 if ( type == BOOL )
00122 {
00123 ret = data.b;
00124 return true;
00125 }
00126 else if ( type == INTEGER )
00127 {
00128 ret = data.l!=0;
00129 return true;
00130 }
00131 else if ( type == FLOAT )
00132 {
00133 ret = data.f!=0;
00134 return true;
00135 }
00136 else
00137 return false;
00138 }
00139
00140 void * PSElement::GetValueV( ) const
00141 {
00142 if ( type == USERDATA )
00143 return data.v;
00144 else
00145 return NULL;
00146 }
00147
00148 bool PSElement::GetValueV( void * & ret )
00149 {
00150 if ( type == USERDATA )
00151 {
00152 ret = data.v;
00153 return true;
00154 } else
00155 return false;
00156 }
00157
00158 PSElement::ParmType PSElement::GetType() const
00159 {
00160 return type;
00161 }
00162
00163 PStack::PStack( const char * sIn, int iMaxLength )
00164 {
00165 if ( iMaxLength <= 0 )
00166 return;
00167
00168 int iCtr = 0;
00169 int iParenDepth = 0;
00170 char cCurrent = sIn[iCtr];
00171
00172 MString sCurrent;
00173 PSElement::ParmType pt = PSElement::FLOAT;
00174 bool bInString = false;
00175
00176 while ( ( cCurrent != '\0' ) && ( iCtr < iMaxLength ) )
00177 {
00178 if ( cCurrent == '\"' )
00179 {
00180 pt = PSElement::STRING;
00181 bInString = !bInString;
00182 iCtr++;
00183 cCurrent = sIn[iCtr];
00184 }
00185
00186 if ( bInString )
00187 sCurrent += cCurrent;
00188 else
00189 switch ( cCurrent )
00190 {
00191 case ',':
00192 if ( iParenDepth > 0 )
00193 {
00194 sCurrent += cCurrent;
00195 break;
00196 }
00197 if ( pt == PSElement::STRING )
00198 PushItemBack( PSElement( sCurrent ) );
00199 else if ( pt == PSElement::FLOAT )
00200 PushItemBack( PSElement( float( atof( sCurrent.c_str() ) ) ) );
00201 else
00202 {
00203 PSElement PM = PSElement( atoi( sCurrent.c_str() ) );
00204 PM.ForceType( pt );
00205 PushItemBack( PM );
00206 }
00207 pt = PSElement::FLOAT;
00208 sCurrent = "";
00209 break;
00210 case '(':
00211 iParenDepth++;
00212 break;
00213 case ')':
00214 iParenDepth--;
00215 break;
00216 case '%':
00217 if ( iParenDepth > 0 )
00218 {
00219 sCurrent += cCurrent;
00220 break;
00221 }
00222 if ( sCurrent.empty() )
00223 pt = PSElement::PARAMETER;
00224 break;
00225 default:
00226 sCurrent += cCurrent;
00227 }
00228 iCtr++;
00229 cCurrent = sIn[iCtr];
00230 }
00231 if ( pt == PSElement::STRING )
00232 PushItemBack( PSElement( sCurrent ) );
00233 else if ( pt == PSElement::FLOAT )
00234 PushItemBack( PSElement( float( atof( sCurrent.c_str() ) ) ) );
00235 else
00236 {
00237 PSElement PM = PSElement( atoi( sCurrent.c_str() ) );
00238 PM.ForceType( pt );
00239 PushItemBack( PM );
00240 }
00241 }
00242
00243 PStack::PStack( PSElement p1 )
00244 {
00245 PushItem( p1 );
00246 }
00247
00248 PStack::PStack( PSElement p1, PSElement p2 )
00249 {
00250 PushItem( p2 );
00251 PushItem( p1 );
00252 }
00253
00254 PStack::PStack( PSElement p1, PSElement p2, PSElement p3 )
00255 {
00256 PushItem( p3 );
00257 PushItem( p2 );
00258 PushItem( p1 );
00259 }
00260
00261 PStack::PStack( PSElement p1, PSElement p2, PSElement p3, PSElement p4 )
00262 {
00263 PushItem( p4 );
00264 PushItem( p3 );
00265 PushItem( p2 );
00266 PushItem( p1 );
00267 }
00268
00269 PStack::~PStack()
00270 {
00271 }
00272
00273 void PStack::PushItem(const PSElement & in )
00274 {
00275 m_stack.insert( 0, in );
00276 }
00277
00278 void PStack::PushItemBack(const PSElement & in )
00279 {
00280 m_stack.push_back( in );
00281 }
00282
00283 bool PStack::PopItem( PSElement & out )
00284 {
00285 if ( m_stack.empty() )
00286 return false;
00287
00288 out = m_stack[0];
00289
00290 m_stack.remove( 0 );
00291 return true;
00292 }
00293
00294 bool PStack::PeekItem( PSElement & out )
00295 {
00296 if ( m_stack.empty() )
00297 return false;
00298 out = m_stack[0];
00299 return true;
00300 }
00301
00302 PSElement PStack::PopItem()
00303 {
00304 if ( m_stack.empty() )
00305 return NILElement;
00306 PSElement ret = m_stack[0];
00307 m_stack.remove( 0 );
00308 return ret;
00309 }
00310
00311 const PSElement& PStack::PeekItem( unsigned int iAhead ) const
00312 {
00313 if (iAhead < m_stack.size())
00314 return m_stack[iAhead];
00315 return NILElement;
00316 }
00317
00318
00319 MVector< PStack * > g_vMPStacks;
00320
00321 int HGEXPORT CreateMPStack()
00322 {
00323 unsigned i;
00324 for( i = 0; i < g_vMPStacks.size(); i++ )
00325 if ( !g_vMPStacks[i] )
00326 break;
00327
00328 if ( i == g_vMPStacks.size() )
00329 g_vMPStacks.push_back( new PStack );
00330 else
00331 g_vMPStacks[i] = new PStack;
00332
00333 g_vMPStacks[i]->Clear();
00334
00335 return i;
00336 }
00337
00338 int HGEXPORT GetMPStackSize( unsigned int iMPS )
00339 {
00340 if ( iMPS >= g_vMPStacks.size() )
00341 return -1;
00342 else if ( g_vMPStacks[iMPS] )
00343 return g_vMPStacks[iMPS]->GetSize();
00344 else
00345 return -1;
00346 }
00347
00348 const char * HGEXPORT GetMPStackAtS( unsigned int iMPS, unsigned int iPL )
00349 {
00350 if ( iMPS >= g_vMPStacks.size() )
00351 return NULL;
00352 else if ( !g_vMPStacks[ iMPS ] )
00353 return NULL;
00354 else if ( iPL >= g_vMPStacks[ iMPS ]->GetSize() )
00355 return NULL;
00356 return g_vMPStacks[ iMPS ]->PeekItem( iPL ).GetValueS().c_str();
00357 }
00358
00359 int HGEXPORT GetMPStackAtI( unsigned int iMPS, unsigned int iPL )
00360 {
00361 if ( iMPS >= g_vMPStacks.size() )
00362 return 0;
00363 else if ( !g_vMPStacks[ iMPS ] )
00364 return 0;
00365 else if ( iPL >= g_vMPStacks[ iMPS ]->GetSize() )
00366 return 0;
00367 return g_vMPStacks[ iMPS ]->PeekItem( iPL ).GetValueI();
00368 }
00369
00370 float HGEXPORT GetMPStackAtF( unsigned int iMPS, unsigned int iPL )
00371 {
00372 if ( iMPS >= g_vMPStacks.size() )
00373 return (float)NULL;
00374 else if ( !g_vMPStacks[ iMPS ] )
00375 return (float)NULL;
00376 else if ( iPL >= g_vMPStacks[ iMPS ]->GetSize() )
00377 return (float)NULL;
00378 return g_vMPStacks[ iMPS ]->PeekItem( iPL ).GetValueF();
00379 }
00380
00381 void HGEXPORT PushMPStackBackS( unsigned int iMPS, const char * s )
00382 {
00383 if ( iMPS >= g_vMPStacks.size() )
00384 return;
00385 else if ( !g_vMPStacks[ iMPS ] )
00386 return;
00387 g_vMPStacks[iMPS]->PushItem( PSElement( MString( s ) ) );
00388 }
00389
00390 void HGEXPORT PushMPStackBackI( unsigned int iMPS, int i )
00391 {
00392 if ( iMPS >= g_vMPStacks.size() )
00393 return;
00394 else if ( !g_vMPStacks[ iMPS ] )
00395 return;
00396 g_vMPStacks[iMPS]->PushItem( PSElement( i ) );
00397 }
00398
00399 void HGEXPORT PushMPStackBackF( unsigned int iMPS, float f )
00400 {
00401 if ( iMPS >= g_vMPStacks.size() )
00402 return;
00403 else if ( !g_vMPStacks[ iMPS ] )
00404 return;
00405 g_vMPStacks[iMPS]->PushItem( PSElement( f ) );
00406 }
00407
00408 void HGEXPORT DeleteMPStack( unsigned int iMPS )
00409 {
00410 SAFE_DELETE( g_vMPStacks[iMPS] );
00411 g_vMPStacks[iMPS] = NULL;
00412 }
00413
00414 void HGEXPORT FlushMPStacks()
00415 {
00416 for( unsigned i = 0; i < g_vMPStacks.size(); i++ )
00417 if( g_vMPStacks[i] )
00418 SAFE_DELETE( g_vMPStacks[i] );
00419 }
00420
00421 PStack * GetMPStack( unsigned int iMPS )
00422 {
00423 if ( iMPS >= g_vMPStacks.size() )
00424 return NULL;
00425 else if ( !g_vMPStacks[ iMPS ] )
00426 return NULL;
00427 return g_vMPStacks[iMPS];
00428 }
00429
00430
00431
00432
00433 PSElement PSElement::Operate( const MString & sOperator, const PSElement & pRHS )
00434 {
00435 PSElement ret;
00436 if( sOperator.length() == 0 )
00437 {
00438 LOG.Warn( "NULL Operator used!" );
00439 return NILElement;
00440 }
00441
00442 char sFirstChar = sOperator.c_str()[0];
00443 char sSecondChar = sOperator.c_str()[1];
00444 long lLength = sOperator.length();
00445
00446 if( sFirstChar <= '.' )
00447 {
00448 if( sFirstChar == '!' )
00449 {
00450 if( sSecondChar == '=' && lLength == 2 )
00451 {
00452 ret.type = BOOL;
00453 ret.data.b = ( GetValueS().compare( pRHS.GetValueS() ) != 0 );
00454 return ret;
00455 }
00456 if( lLength == 1 )
00457 {
00458 ret.type = BOOL;
00459 ret.data.b = !GetValueB();
00460 return ret;
00461 }
00462 }
00463 if( sFirstChar == '*' )
00464 {
00465 if( sSecondChar == '=' && lLength == 2 )
00466 {
00467 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00468 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00469 {
00470 LOG.Warn( "Incompatible types for operator *" );
00471 return NILElement;
00472 }
00473 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00474 {
00475 data.f = GetValueF() * pRHS.GetValueF();
00476 type = FLOAT;
00477 } else {
00478 data.l = GetValueI() * pRHS.GetValueI();
00479 type = INTEGER;
00480 }
00481 return (*this);
00482 } else if( lLength == 1 )
00483 {
00484 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00485 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00486 {
00487 LOG.Warn( "Incompatible types for operator *" );
00488 return NILElement;
00489 }
00490 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00491 {
00492 ret.data.f = GetValueF() * pRHS.GetValueF();
00493 ret.type = FLOAT;
00494 } else {
00495 ret.data.l = GetValueI() * pRHS.GetValueI();
00496 ret.type = INTEGER;
00497 }
00498 return ret;
00499 }
00500 }
00501 if( sFirstChar == '+' )
00502 {
00503 if( sSecondChar == '=' && lLength == 2 )
00504 {
00505 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00506 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00507 {
00508 LOG.Warn( "Incompatible types for operator +" );
00509 return NILElement;
00510 }
00511 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00512 {
00513 data.f = GetValueF() + pRHS.GetValueF();
00514 type = FLOAT;
00515 } else {
00516 data.l = GetValueI() + pRHS.GetValueI();
00517 type = INTEGER;
00518 }
00519 return (*this);
00520 } else if( lLength == 1 )
00521 {
00522 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00523 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00524 {
00525 LOG.Warn( "Incompatible types for operator +" );
00526 return NILElement;
00527 }
00528 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00529 {
00530 ret.data.f = GetValueF() + pRHS.GetValueF();
00531 ret.type = FLOAT;
00532 } else {
00533 ret.data.l = GetValueI() + pRHS.GetValueI();
00534 ret.type = INTEGER;
00535 }
00536 return ret;
00537 }
00538 }
00539 if( sFirstChar == '-' )
00540 {
00541 if( sSecondChar == '=' && lLength == 2 )
00542 {
00543 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00544 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00545 {
00546 LOG.Warn( "Incompatible types for operator -" );
00547 return NILElement;
00548 }
00549 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00550 {
00551 data.f = GetValueF() - pRHS.GetValueF();
00552 type = FLOAT;
00553 } else {
00554 data.l = GetValueI() - pRHS.GetValueI();
00555 type = INTEGER;
00556 }
00557 return (*this);
00558 } else if( lLength == 1 )
00559 {
00560 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00561 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00562 {
00563 LOG.Warn( "Incompatible types for operator -" );
00564 return NILElement;
00565 }
00566 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00567 {
00568 ret.data.f = GetValueF() - pRHS.GetValueF();
00569 ret.type = FLOAT;
00570 } else {
00571 ret.data.l = GetValueI() - pRHS.GetValueI();
00572 ret.type = INTEGER;
00573 }
00574 return ret;
00575 }
00576 }
00577 if( sFirstChar == '.' )
00578 {
00579 if( sSecondChar == '=' && lLength == 2 )
00580 {
00581 if( type == STRING )
00582 delete data.dataS;
00583 type = STRING;
00584 data.dataS = new MString( GetValueS() + pRHS.GetValueS() );
00585 return (*this);
00586
00587 } else if( lLength == 1 )
00588 {
00589 if( ret.type == STRING )
00590 delete data.dataS;
00591 ret.type = STRING;
00592 ret.data.dataS = new MString( GetValueS() + pRHS.GetValueS() );
00593 return ret;
00594 }
00595 }
00596 } else {
00597 if( sFirstChar == '=' )
00598 {
00599 if( sSecondChar == '=' && lLength == 2 )
00600 {
00601 ret.type = BOOL;
00602 ret.data.b = ( GetValueS().compare( pRHS.GetValueS() ) == 0 );
00603 return ret;
00604 }
00605 if( lLength == 1 )
00606 {
00607 type = pRHS.type;
00608 if( pRHS.type == STRING )
00609 {
00610 if( type == STRING )
00611 *data.dataS = *pRHS.data.dataS;
00612 else
00613 data.dataS = new MString( *pRHS.data.dataS );
00614 }
00615 else
00616 data = pRHS.data;
00617 return (*this);
00618 }
00619 }
00620 if( sFirstChar == '>' )
00621 {
00622 if( sSecondChar == '=' && lLength == 2 )
00623 {
00624 ret.type = BOOL;
00625 ret.data.b = GetValueF() >= pRHS.GetValueF();
00626 return ret;
00627 }
00628 if( lLength == 1 )
00629 {
00630 ret.type = BOOL;
00631 ret.data.b = GetValueF() > pRHS.GetValueF();
00632 return ret;
00633 }
00634 }
00635 if( sFirstChar == '<' )
00636 {
00637 if( sSecondChar == '=' && lLength == 2 )
00638 {
00639 ret.type = BOOL;
00640 ret.data.b = GetValueF() <= pRHS.GetValueF();
00641 return ret;
00642 }
00643 if( lLength == 1 )
00644 {
00645 ret.type = BOOL;
00646 ret.data.b = GetValueF() < pRHS.GetValueF();
00647 return ret;
00648 }
00649 }
00650 if( sFirstChar == '/' )
00651 {
00652 if( sSecondChar == '=' && lLength == 2 )
00653 {
00654 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00655 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00656 {
00657 LOG.Warn( "Incompatible types for operator /" );
00658 return NILElement;
00659 }
00660 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00661 {
00662 data.f = GetValueF() / pRHS.GetValueF();
00663 type = FLOAT;
00664 } else {
00665 data.l = GetValueI() / pRHS.GetValueI();
00666 type = INTEGER;
00667 }
00668 return (*this);
00669 } else if( lLength == 1 )
00670 {
00671 if( ( GetType() != INTEGER && GetType() != FLOAT ) ||
00672 ( pRHS.GetType() != INTEGER && pRHS.GetType() != FLOAT ) )
00673 {
00674 LOG.Warn( "Incompatible types for operator /" );
00675 return NILElement;
00676 }
00677 if( GetType() == FLOAT || pRHS.GetType() == FLOAT )
00678 {
00679 ret.data.f = GetValueF() / pRHS.GetValueF();
00680 ret.type = FLOAT;
00681 } else {
00682 ret.data.l = GetValueI() / pRHS.GetValueI();
00683 ret.type = INTEGER;
00684 }
00685 return ret;
00686 }
00687 }
00688 }
00689
00690 LOG.Warn( "Operator '" + sOperator + "' unknown." );
00691 return NILElement;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726