rpn_handler.cpp

Go to the documentation of this file.
00001 
00002 // Name:        rpn_handler.cpp
00003 // Purpose:     
00004 // Author:      NDA
00005 // Modified by: 
00006 // Created:     09/01/07 16:54
00007 // RCS-ID:      
00008 // Copyright:   CAEN S.p.A All rights reserved.
00009 // Licence:     
00011 
00012 
00013 #if defined(__GNUG__) && !defined(__APPLE__)
00014 #pragma implementation "rpn_handler.h"
00015 #endif
00016 
00017 
00018 #ifdef __BORLANDC__
00019 #pragma hdrstop
00020 #endif
00021 
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <stdio.h>
00025 
00026 #include "rpn_handler.h"
00027 #include "virtual_board_channel.h"
00028 
00029 RpnHandler::RpnHandler( VirtualBoardChannel* parent, const char *expression_def)
00030 {
00031         this->m_parent= parent;
00032         this->m_rpn_items_array= NULL;
00033         this->m_tmp_rpn_items_array= NULL;
00034         this->m_rpn_array_alloc_size= 0;
00035         this->m_rpn_array_real_size= 0;
00036         this->m_expression_def= NULL;
00037         this->m_ref_channel_index= -1;
00038         this->Parse( expression_def);
00039 }
00040 
00041 RpnHandler::~RpnHandler(void)
00042 {
00043         if( this->m_rpn_items_array!= NULL)
00044                 delete[] this->m_rpn_items_array;
00045         if( this->m_tmp_rpn_items_array)
00046                 delete[] this->m_tmp_rpn_items_array;
00047         if( this->m_expression_def)
00048                 delete this->m_expression_def;
00049 
00050 }
00051 
00052 bool RpnHandler::Parse( const char *expression_def)
00053 {
00054         //
00055         // Parse input string and build items array:
00056         // tokens must be ',' separated, upper or lower case, but no white space trimming will be performed !
00057 
00058         const int BLOCK_ALLOC_SIZE= 10;
00059         char* token;
00060         char* tmp_buff;
00061         this->m_ref_channel_index= -1;
00062         if( this->m_expression_def)
00063                 delete this->m_expression_def;
00064         this->m_expression_def= new char[ strlen( expression_def)+ 1];
00065         tmp_buff= new char[ strlen( expression_def)+ 1];
00066         strcpy( this->m_expression_def, expression_def);
00067         strcpy( tmp_buff, expression_def);
00068 
00069         if( this->m_rpn_items_array!= NULL)
00070                 delete[] this->m_rpn_items_array;
00071 
00072         this->m_rpn_array_alloc_size= BLOCK_ALLOC_SIZE;
00073         this->m_rpn_items_array= new RpnItem[ this->m_rpn_array_alloc_size];
00074         this->m_rpn_array_real_size= 0;
00075 
00076         token= strtok( tmp_buff, ",");
00077         while( token!= NULL)
00078         {
00079                 if( this->m_rpn_array_real_size> this->m_rpn_array_alloc_size)
00080                 {
00081                         // Realloc
00082                         RpnItem *tmp= new RpnItem[ this->m_rpn_array_alloc_size+ BLOCK_ALLOC_SIZE];
00083                         memcpy( tmp, this->m_rpn_items_array, sizeof( this->m_rpn_items_array[0])* this->m_rpn_array_alloc_size);
00084                         delete[] this->m_rpn_items_array;
00085                         this->m_rpn_items_array= tmp;
00086                         this->m_rpn_array_alloc_size+= BLOCK_ALLOC_SIZE;
00087                 }
00088 
00089                 this->m_rpn_items_array[ this->m_rpn_array_real_size].m_processed= false;
00090                 this->m_rpn_items_array[ this->m_rpn_array_real_size].m_type= (RpnTypes)-1;
00091                 // Check if operator or operand
00092                 for( int i= 0; i< RPN_OPERAND_CONST; i++)
00093                 {
00094                         if( !stricmp( token, RpnTypesNames[ i]))
00095                         {
00096                                 //
00097                                 // found
00098                                 this->m_rpn_items_array[ this->m_rpn_array_real_size].m_type= (RpnTypes)i;
00099                                 this->m_rpn_items_array[ this->m_rpn_array_real_size].m_value= 0;       // Don't care
00100 
00101                                 if( this->m_ref_channel_index== -1)
00102                                 {
00103                                         switch( i)
00104                                         {
00105                                         case RPN_OPERAND_CH0:           // Channel 0 Operand
00106                                         case RPN_OPERAND_CH1:           // Channel 1 Operand
00107                                         case RPN_OPERAND_CH2:           // Channel 2 Operand
00108                                         case RPN_OPERAND_CH3:           // Channel 3 Operand
00109                                         case RPN_OPERAND_CH4:           // Channel 4 Operand
00110                                         case RPN_OPERAND_CH5:           // Channel 5 Operand
00111                                         case RPN_OPERAND_CH6:           // Channel 6 Operand
00112                                         case RPN_OPERAND_CH7:           // Channel 7 Operand
00113                                                 this->m_ref_channel_index= i- RPN_OPERAND_CH0;
00114                                                 break;
00115                                         }
00116                                 }
00117 
00118                                 break;
00119                         }
00120                 }
00121                 
00122                 if( this->m_rpn_items_array[ this->m_rpn_array_real_size].m_type== (RpnTypes)-1)
00123                 {
00124                         // Literal operand type
00125                         this->m_rpn_items_array[ this->m_rpn_array_real_size].m_type= RPN_OPERAND_CONST;
00126                         this->m_rpn_items_array[ this->m_rpn_array_real_size].m_value= atof( token);
00127                 }
00128                 this->m_rpn_array_real_size++;
00129 
00130                 token= strtok( NULL, ",");
00131         }
00132         delete tmp_buff;
00133         if( this->m_tmp_rpn_items_array)
00134                 delete[] this->m_tmp_rpn_items_array;
00135         this->m_tmp_rpn_items_array= new RpnItem[ this->m_rpn_array_alloc_size];
00136 
00137         return true;
00138 }
00139 const char* RpnHandler::Format( )
00140 {
00141         return this->m_expression_def? this->m_expression_def: "";
00142 }
00143 bool RpnHandler::Test( void)
00144 {
00145         /*
00146                 Just test without calculation
00147         */
00148         return this->DoEval( NULL);
00149 }
00150 bool RpnHandler::Eval( double &result)
00151 {
00152         return this->DoEval( &result);
00153 }
00154 bool RpnHandler::DoEval( double *p_result)
00155 {
00156         /*
00157                 BASIC CONCEPT
00158                 1. No more items? jump to 10
00159                 2. Not an Operator ? jump to 1
00160                 3. Back search erca the first 2 unprocessed items; label them as processed, unprocessed-= 2
00161                 4. Calculate the result and save into operator item: change item type to OPERAND_CONST
00162                 5. Jump to 1
00163                 10.Unprocessed!= 1 ? exit with error
00164                 11.Back search the first (and only) unprocessed item and return result
00165         */
00166         if( p_result)
00167                 *p_result= 0;
00168 
00169         // Make an array work copy 
00170         memcpy( this->m_tmp_rpn_items_array, this->m_rpn_items_array, this->m_rpn_array_real_size* sizeof( this->m_rpn_items_array[ 0]));
00171 
00172         int current_index= 0; 
00173         int num_unprocessed= this->m_rpn_array_real_size;
00174 
00175         // Loop items
00176         for( current_index= 0; current_index< this->m_rpn_array_real_size; current_index++)
00177         {
00178                 if( this->m_tmp_rpn_items_array[ current_index].m_processed)
00179                         continue;
00180                 // Check item type
00181                 switch( this->m_tmp_rpn_items_array[ current_index].m_type)
00182                 {
00183                         case RPN_OPERATOR_ADD:          // Add Operator
00184                         case RPN_OPERATOR_SUB:          // Subtract Operator
00185                         case RPN_OPERATOR_MUL:          // Multiply Operator
00186                         case RPN_OPERATOR_DIV:          // Divide Operator
00187                                 break;
00188                         case RPN_OPERAND_CH0:           // Channel 0 Operand
00189                         case RPN_OPERAND_CH1:           // Channel 1 Operand
00190                         case RPN_OPERAND_CH2:           // Channel 2 Operand
00191                         case RPN_OPERAND_CH3:           // Channel 3 Operand
00192                         case RPN_OPERAND_CH4:           // Channel 4 Operand
00193                         case RPN_OPERAND_CH5:           // Channel 5 Operand
00194                         case RPN_OPERAND_CH6:           // Channel 6 Operand
00195                         case RPN_OPERAND_CH7:           // Channel 7 Operand
00196                                 continue;
00197                         case RPN_OPERAND_CONST:         // Constant value Operand : let as the least
00198                                 continue;
00199                         default:
00200                                 // Unknown type ?
00201                                 return false;
00202                 }
00203                 // Operator found:
00204                 // Get previous two unprocessed operand items
00205                 double operands[ 2]= { 0, 0};
00206                 int back_index= current_index- 1; 
00207                 for( int operand= 0; operand< 2; operand++)
00208                 {
00209                         bool search= true;
00210                         for( ; ( back_index>= 0)&& search; back_index--)
00211                         {
00212                                 if( this->m_tmp_rpn_items_array[ back_index].m_processed)
00213                                         continue;
00214                                 switch( this->m_tmp_rpn_items_array[ back_index].m_type)
00215                                 {
00216                                         case RPN_OPERAND_CH0:           // Channel 0 Operand
00217                                         case RPN_OPERAND_CH1:           // Channel 1 Operand
00218                                         case RPN_OPERAND_CH2:           // Channel 2 Operand
00219                                         case RPN_OPERAND_CH3:           // Channel 3 Operand
00220                                         case RPN_OPERAND_CH4:           // Channel 4 Operand
00221                                         case RPN_OPERAND_CH5:           // Channel 5 Operand
00222                                         case RPN_OPERAND_CH6:           // Channel 6 Operand
00223                                         case RPN_OPERAND_CH7:           // Channel 7 Operand
00224                                                 if( p_result)
00225                                                 {
00226                                                         if( !this->m_parent->GetChannelValueVolt( this->m_tmp_rpn_items_array[ back_index].m_type- RPN_OPERAND_CH0, operands[ operand]))
00227                                                                 return false;
00228                                                         operands[ operand]*= 1000;
00229                                                 }
00230                                                 this->m_tmp_rpn_items_array[ back_index].m_processed= true;
00231                                                 search= false;
00232                                                 num_unprocessed--;
00233                                                 break;
00234                                         case RPN_OPERAND_CONST:         // Constant value Operand : let as the least
00235                                                 if( p_result)
00236                                                 {
00237                                                         operands[ operand]= this->m_tmp_rpn_items_array[ back_index].m_value;
00238                                                 }
00239                                                 this->m_tmp_rpn_items_array[ back_index].m_processed= true;
00240                                                 search= false;
00241                                                 num_unprocessed--;
00242                                                 break;
00243                                         default:
00244                                                 // Unknown operand ?
00245                                                 return false;
00246                                 }
00247                         }
00248                         if( search)
00249                         {
00250                                 // Operands not found ?
00251                                 return false;
00252                         }
00253                 }
00254 
00255                 // Perform the operation
00256                 switch( this->m_tmp_rpn_items_array[ current_index].m_type)
00257                 {
00258                         case RPN_OPERATOR_ADD:          // Add Operator
00259                                 if( p_result)
00260                                 {
00261                                         this->m_tmp_rpn_items_array[ current_index].m_value= operands[ 1]+ operands[ 0];
00262                                 }
00263                                 break;
00264                         case RPN_OPERATOR_SUB:          // Subtract Operator
00265                                 if( p_result)
00266                                 {
00267                                         this->m_tmp_rpn_items_array[ current_index].m_value= operands[ 1]- operands[ 0];
00268                                 }
00269                                 break;
00270                         case RPN_OPERATOR_MUL:          // Multiply Operator
00271                                 if( p_result)
00272                                 {
00273                                         this->m_tmp_rpn_items_array[ current_index].m_value= operands[ 1]* operands[ 0];
00274                                 }
00275                                 break;
00276                         case RPN_OPERATOR_DIV:          // Divide Operator
00277                                 if( p_result)
00278                                 {
00279                                         if( operands[ 0]== 0)
00280                                                 return false;
00281                                         this->m_tmp_rpn_items_array[ current_index].m_value= operands[ 1]/ operands[ 0];
00282                                 }
00283                                 break;
00284                         default:
00285                                 // Unknown operator ?
00286                                 return false;
00287                 }
00288                 this->m_tmp_rpn_items_array[ current_index].m_type= RPN_OPERAND_CONST;
00289         }
00290 
00291         // consistency check
00292         if( num_unprocessed!= 1)
00293                 return false;
00294 
00295         // Get the result: the only unprocessed item
00296         for( int back_index= this->m_rpn_array_real_size- 1; back_index>= 0; back_index--)
00297         {
00298                 if( this->m_tmp_rpn_items_array[ back_index].m_processed)
00299                         continue;
00300                 // found
00301                 switch( this->m_tmp_rpn_items_array[ back_index].m_type)
00302                 {
00303                         case RPN_OPERAND_CH0:           // Channel 0 Operand
00304                         case RPN_OPERAND_CH1:           // Channel 1 Operand
00305                         case RPN_OPERAND_CH2:           // Channel 2 Operand
00306                         case RPN_OPERAND_CH3:           // Channel 3 Operand
00307                         case RPN_OPERAND_CH4:           // Channel 4 Operand
00308                         case RPN_OPERAND_CH5:           // Channel 5 Operand
00309                         case RPN_OPERAND_CH6:           // Channel 6 Operand
00310                         case RPN_OPERAND_CH7:           // Channel 7 Operand
00311                                 if( p_result)
00312                                 {
00313                                         if( !this->m_parent->GetChannelValueVolt( this->m_tmp_rpn_items_array[ back_index].m_type- RPN_OPERAND_CH0, *p_result))
00314                                                 return false;
00315                                 }
00316                                 return true;
00317                         case RPN_OPERAND_CONST:         // Constant value Operand : let as the least
00318                                 if( p_result)
00319                                 {
00320                                         *p_result= this->m_tmp_rpn_items_array[ back_index].m_value* 0.001;
00321                                 }
00322                                 return true;
00323                         default:
00324                                 // Unknown operand ?
00325                                 return false;
00326                 }
00327         }
00328         return true;
00329 }
00330 
00331 unsigned int RpnHandler::GetBufferCount( void)
00332 {
00333         if( this->m_ref_channel_index< 0)
00334                 return (unsigned int)-1;
00335         unsigned int value= 0;
00336         if( !this->m_parent->GetChannelBufferCount( this->m_ref_channel_index, value))
00337                 return (unsigned int)-1;
00338         return value;
00339 }
00340 

Generated on Mon Mar 19 17:14:08 2007 for CAENScope by  doxygen 1.4.6-NO