Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

expandlib-cmd-if.h

Go to the documentation of this file.
00001 
00002 /* This file is part of Expandlib.
00003 
00004   Copyright (C) 2002 Jasper van de Gronde
00005 
00006   This software is provided 'as-is', without any express or implied
00007   warranty.  In no event will the authors be held liable for any damages
00008   arising from the use of this software.
00009 
00010   Permission is granted to anyone to use this software for any purpose,
00011   including commercial applications, and to alter it and redistribute it
00012   freely, subject to the following restrictions:
00013 
00014   1. The origin of this software must not be misrepresented; you must not
00015      claim that you wrote the original software. If you use this software
00016      in a product, an acknowledgment in the product documentation would be
00017      appreciated but is not required.
00018   2. Altered source versions must be plainly marked as such, and must not be
00019      misrepresented as being the original software.
00020   3. This notice may not be removed or altered from any source distribution.
00021 
00022   Jasper van de Gronde th.v.d.gronde@hccnet.nl
00023 
00024 */
00025 
00030 #ifndef EXPANDLIB_CMD_IF_H_INCLUDED
00031 #define EXPANDLIB_CMD_IF_H_INCLUDED
00032 
00033 #include <locale>
00034 
00035 #include <boost/lexical_cast.hpp>
00036 
00037 #include "expandlib-cmd.h"
00038 
00039 namespace expander { // *** Start of namespace
00040 
00042 
00049     template<
00050         // Used for the expandable string (and the expanded string)
00051         class StringType = ::std::string
00052         >
00053     class expcmd_if : public expandcmd<StringType> {
00054     protected:
00055 
00057         inline bool IsValidOpStartChar(const StringType::value_type ch) const throw()
00058         {
00059             return ( ch == _T('<') || ch == _T('>') || ch == _T('=') || ch == _T('!') );
00060         };
00061 
00063         inline bool IsValidOpChar(const StringType::value_type ch) const throw()
00064         {
00065             return ( ch == _T('<') || ch == _T('>') || ch == _T('=') || ch == _T('!') || ch == _T('@') );
00066         };
00067 
00069         const std::locale loc;
00071 //      const std::collate<StringType::value_type> &col;
00072 
00073     public:
00075 
00078         expcmd_if(expandable<StringType> * const eobj) : expandcmd<StringType>(eobj, _T("if")), loc("") {};
00079 
00091         virtual void operator()(StringType &dest, const FParamVectorType &params, const FVarMapType &vars, ExpandResultsType &results) const
00092         {
00093             if ( params.size() == 3 ) {
00094                 ExpandResultsType result;   // Used to verify that all vars were found
00095 
00096                 {
00097                     StringType d;
00098                     expobj->expand(d, params[0], vars, result); // Expand operand 1
00099                 }
00100 
00101                 {
00102                     //StringType d;
00103                     if ( result.MissedVars() == 0 ) {
00104                         /*if ( */expobj->expand(dest, params[1], vars, results);// ) dest+=d;
00105                     } else {
00106                         /*if ( */expobj->expand(dest, params[2], vars, results);// ) dest+=d;
00107                     }
00108                 }
00109             } else if ( params.size() == 5 ) {
00110                 if ( params[1].size() > 3 ) {
00111                     throw expand_error(_T("expcmd_if"),_T("Illegal operator"),params[1].c_str());
00112                 }
00113 
00114                 StringType operand1, operand2;  // The two operands for the comparison
00115                 struct {
00116                     bool equalto;
00117                     bool greaterthan;
00118                     bool lessthan;
00119                     bool not;
00120                 } comp;         // Keeps track of the comparisons needed
00121                 enum {
00122                     nocomp,
00123                     binary,
00124                     textual,
00125                     numeric
00126                 } comptype;     // Keeps track of the comparison type
00127                 ExpandResultsType resultop1, resultop2; // Used to verify that all vars were found
00128 
00129                 expobj->expand(operand1, params[0], vars, resultop1);   // Expand operand 1
00130                 expobj->expand(operand2, params[2], vars, resultop2);   // Expand operand 2
00131 
00132                 // Collect info about the comparison
00133                 comp.equalto=false;
00134                 comp.greaterthan=false;
00135                 comp.lessthan=false;
00136                 comp.not=false;
00137                 comptype=nocomp;
00138 
00139                 {
00140                     StringType op(params[1]);
00141                     if ( op.size() >= 1 ) {
00142                         comptype=binary;
00143                         if ( op.size() >= 2 ) {
00144                             if ( op[op.size()-1] == _T('@') ) {
00145                                 comptype=textual;
00146                                 op.erase(op.end() - 1);
00147                             } else if ( op[op.size()-1] == _T('!') ) {
00148                                 comptype=numeric;
00149                                 op.erase(op.end() - 1);
00150                             } else if ( op.size() == 3 && op[op.size()-1] == _T('=') ) {
00151                                 op.erase(op.end() - 1);
00152                             }
00153                         }
00154 
00155                         if ( op == _T("==") ) {
00156                             comp.equalto=true;
00157                         } else if ( op == _T(">=") ) {
00158                             comp.equalto=true;
00159                             comp.greaterthan=true;
00160                         } else if ( op == _T("<=") ) {
00161                             comp.equalto=true;
00162                             comp.lessthan=true;
00163                         } else if ( op == _T("!=") ) {
00164                             comp.equalto=true;
00165                             comp.not=true;
00166                         } else if ( op == _T(">") ) {
00167                             comp.greaterthan=true;
00168                         } else if ( op == _T("<") ) {
00169                             comp.lessthan=true;
00170                         } else {
00171                             comptype=nocomp;
00172                         }
00173                     }
00174                 }
00175 
00176                 {
00177                     //StringType d;
00178                     bool correct=false; // correct keeps track of wether or not the comparison is true
00179                                         //  It does that by initializing to false and then ORing
00180                                         //  with true for each comparison that is true. At the end
00181                                         //  it checks wether it needs to NOT the comparison.
00182                                         //  The comparison could be done slightly more compact by
00183                                         //  either "jumping" as soon as something was true, or by
00184                                         //  doing something like: correct=correct || ( operand1 == operand2 )
00185                     switch(comptype) {
00186                     case binary:
00187                         {   // This performs a "binary" comparison (or should perform one at least)
00188                             if ( comp.equalto ) {
00189                                 if ( operand1 == operand2 ) correct=correct || true;
00190                             }
00191                             if ( comp.greaterthan ) {
00192                                 if ( operand1 > operand2 ) correct=correct || true;
00193                             }
00194                             if ( comp.lessthan ) {
00195                                 if ( operand1 < operand2 ) correct=correct || true;
00196                             }
00197                             if ( comp.not ) {
00198                                 correct=(correct?false:true);
00199                             }
00200                             if ( correct ) {
00201                                 /*if ( */expobj->expand(dest, params[3], vars, results);// ) dest+=d;
00202                             } else {
00203                                 /*if ( */expobj->expand(dest, params[4], vars, results);// ) dest+=d;
00204                             }
00205                         }
00206                         break;
00207                     case textual:
00208                         {   // This should perform a "textual" comparison (more or less what a dictionary uses)
00209                             using namespace std;
00210                             use_facet< ctype<StringType::value_type> >(loc).toupper(operand1.begin(), operand1.end());
00211                             use_facet< ctype<StringType::value_type> >(loc).toupper(operand2.begin(), operand2.end());
00212                             if ( comp.equalto ) {
00213                                 if ( operand1 == operand2 ) correct=correct || true;
00214                             }
00215                             if ( comp.greaterthan ) {
00216                                 if ( operand1 > operand2 ) correct=correct || true;
00217                             }
00218                             if ( comp.lessthan ) {
00219                                 if ( operand1 < operand2 ) correct=correct || true;
00220                             }
00221                             if ( comp.not ) {
00222                                 correct=(correct?false:true);
00223                             }
00224                             if ( correct ) {
00225                                 /*if ( */expobj->expand(dest, params[3], vars, results);// ) dest+=d;
00226                             } else {
00227                                 /*if ( */expobj->expand(dest, params[4], vars, results);// ) dest+=d;
00228                             }
00229                         }
00230                         break;
00231                     case numeric:
00232                         {   // This performs a numeric conversion (10 is bigger than 8)
00233                             try {
00234                                 const int num1=boost::lexical_cast<int>(operand1);//*/atoi(operand1.c_str());
00235                                 const int num2=boost::lexical_cast<int>(operand2);//*/atoi(operand2.c_str());
00236 
00237                                 if ( comp.equalto ) {
00238                                     if ( num1 == num2 ) correct=correct || true;
00239                                 }
00240                                 if ( comp.greaterthan ) {
00241                                     if ( num1 > num2 ) correct=correct || true;
00242                                 }
00243                                 if ( comp.lessthan ) {
00244                                     if ( num1 < num2 ) correct=correct || true;
00245                                 }
00246                                 if ( comp.not ) {
00247                                     correct=(correct?false:true);
00248                                 }
00249                                 if ( correct ) {
00250                                     /*if ( */expobj->expand(dest, params[3], vars, results);// ) dest+=d;
00251                                 } else {
00252                                     /*if ( */expobj->expand(dest, params[4], vars, results);// ) dest+=d;
00253                                 }
00254                             } catch(boost::bad_lexical_cast) {
00255                                 dest+=_T("#Illegal operand(s)#");
00256                                 return;
00257                             }
00258                         }
00259                         break;
00260                     } // End of switch(comptype)
00261                 }
00262             } else {
00263                 throw expand_error(_T("expcmd_if"),_T("Parameter error"));
00264             }
00265         }
00266     };
00267 
00268 } // *** End of namespace
00269 
00270 #endif //EXPANDLIB_CMD_IF_H_INCLUDED

Generated on Tue Feb 4 17:24:13 2003 for ExpandLib by doxygen1.3-rc2