Changeset 333 for cpp/frams/util


Ignore:
Timestamp:
03/01/15 01:19:56 (9 years ago)
Author:
Maciej Komosinski
Message:
  • use source/code mapping for line number and file information in vm error messages
  • enum ExtValue::CompareResult? instead of int
Location:
cpp/frams/util
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/util/extvalue.cpp

    r326 r333  
    1313#include <common/Convert.h>
    1414#include <climits>
     15#include <errno.h>
    1516
    1617#ifndef NO_BARRIER
     
    290291}
    291292
    292 static int longsign(paInt x)
    293 {
    294 if (x<0) return -1;
    295 if (x>0) return 1;
    296 return 0;
    297 }
    298 
    299 static int compareNull(const ExtValue& v)
    300 {
    301 switch(v.type)
    302         {
    303         case TDouble: return v.getDouble()!=0.0;
    304         case TInt: return v.getInt()?1:0;
    305         case TString: return 1;
    306         default: return !v.isNull();
    307         }
    308 }
    309 
    310 int ExtValue::compare(const ExtValue& src) const
     293static ExtValue::CompareResult longsign(paInt x)
     294{
     295if (x<0) return ExtValue::ResultLower;
     296if (x>0) return ExtValue::ResultHigher;
     297return ExtValue::ResultEqual;
     298}
     299
     300static ExtValue::CompareResult compareNull(const ExtValue& v)
     301{
     302if (v.isNull()) return ExtValue::ResultEqualUnordered;
     303if ((v.getType()==TInt)&&(v.getInt()==0)) return ExtValue::ResultUnequal_RelaxedEqual;
     304return ExtValue::ResultUnequal_RelaxedUnequal; //comparing anything else with null is valid but null is neither higher nor lower than numbers or strings
     305}
     306
     307static ExtValue::CompareResult compareFloat(double a,double b)
     308{
     309double t=a-b;
     310if (t<0) return ExtValue::ResultLower;
     311else if (t>0) return ExtValue::ResultHigher;
     312return ExtValue::ResultEqual;
     313}
     314
     315static ExtValue::CompareResult compareString(const SString &a,const SString &b)
     316{
     317const char* s1=(const char*)a;
     318const char* s2=(const char*)b;
     319return longsign(strcmp(s1,s2));
     320}
     321
     322ExtValue::CompareResult ExtValue::compare(const ExtValue& src) const
    311323{
    312324if (isNull())
     
    316328switch(type)
    317329        {
     330
    318331        case TInt:
    319         {
    320         paInt t=src.getInt();
    321         if (idata()>0)
    322                 {if (t>0) return longsign(idata()-t); else return +1;}
    323         else
    324                 {if (t<=0) return longsign(idata()-t); else return -1;}
    325         }
     332
     333                if (src.getType()==TInt)
     334                        {
     335                        paInt t=src.getInt();
     336                        if (idata()>0)
     337                                {if (t>0) return longsign(idata()-t); else return ResultHigher;}
     338                        else
     339                                {if (t<=0) return longsign(idata()-t); else return ResultLower;}
     340                        }
     341                else if (src.getType()==TDouble)
     342                        return compareFloat((double)idata(),src.getDouble());
     343                else
     344                        return ResultMismatch;//comparing numbers with other things is invalid
     345                break;
     346
    326347        case TDouble:
    327                 {
    328                 double t=ddata()-src.getDouble();
    329                 if (t<0) return -1;
    330                 else if (t>0) return 1;
    331                 return 0;
    332                 }
     348                if ((src.getType()==TDouble)||(src.getType()==TInt))
     349                        return compareFloat(getDouble(),src.getDouble());
     350                else
     351                        return ResultMismatch;
     352                break;
     353
    333354        case TString:
    334         {
    335         SString t=src.getString();
    336         SString& t2=sdata();
    337         const char* s1=(const char*)t2;
    338         const char* s2=(const char*)t;
    339         return longsign(strcmp(s1,s2));
    340         }
     355                if (src.getType()==TString)
     356                        return compareString(sdata(),src.getString());
     357                else
     358                        return ResultMismatch;
     359                break;
     360
    341361        case TObj:
    342362        {
    343363        if (src.type==TObj)
    344                 return !(odata()==src.odata());
    345         return 1;
     364                return odata()==src.odata() ? ResultEqualUnordered : ResultUnequal_RelaxedUnequal;
     365        if ((src.type==TInt)&&(src.getInt()==0))
     366                return ResultMismatch_RelaxedUnequal;
     367        return ResultMismatch;
    346368        }
    347369        default:;
    348370        }
    349 return 1;
     371return ResultMismatch;
     372}
     373
     374ExtValue::CmpMessageHandler ExtValue::default_cmp_message;
     375ExtValue::CmpContext ExtValue::default_cmp_context={NULL,NULL,&default_cmp_message};
     376
     377const char* ExtValue::cmp_op_names[]={"==","!=",">=","<=",">","<","~=","!~",NULL};
     378
     379void ExtValue::CmpMessageHandler::cmpMessage(SString& text)
     380{
     381FMprintf("ExtValue","interpretCompare",FMLV_ERROR,"%s",(const char*)text);
     382}
     383
     384int ExtValue::interpretCompare(CmpOperator op,CompareResult result,CmpContext *context)
     385{
     386int err=ResultUnequal_RelaxedEqual;//error when ResultUnequal_RelaxedEqual or higher (not comparable)
     387int ret=0;
     388switch (op)
     389        {
     390        case CmpEQ: ret=(result==ResultEqual)||(result==ResultEqualUnordered); err=ResultMismatch_RelaxedUnequal; break;
     391        case CmpNE: ret=!((result==ResultEqual)||(result==ResultEqualUnordered)); err=ResultMismatch_RelaxedUnequal; break;
     392        case CmpGT: ret=(result==ResultHigher); err=ResultEqualUnordered; break;
     393        case CmpGE: ret=(result==ResultEqual)||(result==ResultHigher); err=ResultEqualUnordered; break;
     394        case CmpLT: ret=(result==ResultLower); err=ResultEqualUnordered; break;
     395        case CmpLE: ret=(result==ResultEqual)||(result==ResultLower); err=ResultEqualUnordered; break;
     396        case CmpREQ: ret=(result==ResultEqual)||(result==ResultEqualUnordered)||(result==ResultUnequal_RelaxedEqual); err=ResultMismatch; break;
     397        case CmpRNE: ret=!((result==ResultEqual)||(result==ResultEqualUnordered)||(result==ResultUnequal_RelaxedEqual)); err=ResultMismatch; break;
     398        default:;
     399        }
     400if (result>=err)
     401        {
     402        if (context)
     403                {
     404                SString msg="Type mismatch";
     405                if (context->v1 && context->v2)
     406                        {
     407                        const char* opname=cmp_op_names[op-CmpFIRST];
     408                        msg+=": ";
     409                        if (context->v1->isNull())
     410                                msg+="null ";
     411                        else
     412                                msg+=SString::sprintf("%s '%s' ",(const char*)context->v1->typeDescription(),(const char*)context->v1->getString());
     413                        msg+=opname;
     414                        if (context->v2->isNull())
     415                                msg+=" null";
     416                        else
     417                                msg+=SString::sprintf(" %s '%s'",(const char*)context->v2->typeDescription(),(const char*)context->v2->getString());
     418                        }
     419                context->handler->cmpMessage(msg);
     420                }
     421        ret=-1;
     422        }
     423return ret;
    350424}
    351425
     
    814888                return ret+1;
    815889        else
     890                {
     891                FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing '\"' in string: '%s'",ret);
    816892                return NULL;
     893                }
    817894        }
    818895else if (*in=='[')
     
    832909                        p=ret;
    833910                        if (*p==',') p++;
     911                        else if (*p!=']')
     912                                {
     913                                FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Vector: '%s'",p);
     914                                return NULL;
     915                                }
    834916                        }
    835917                else
     
    855937                if ((!ret)||(args[1].getType()!=TString)) {p=NULL;break;}
    856938                p=ret;
    857                 if (*p!=':') {p=NULL;break;}
     939                if (*p!=':') {FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ':' in Dictionary: '%s'",p);p=NULL;break;}
    858940                p++;
    859941                ret=args[0].deserialize(p);
     
    862944                dic->p_set(args,&dummy_ret);
    863945                if (*p==',') p++;
     946                else if (*p!='}')
     947                        {
     948                        FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Dictionary: '%s'",p);
     949                        return NULL;
     950                        }
    864951                }
    865952        setObject(o);
     
    899986                        }
    900987                }
     988        FMprintf("ExtValue","deserialize",FMLV_ERROR,"Invalid reference: '%s'",in-1);
    901989        return NULL;
    902990        }
     
    9481036        return ret;
    9491037        }
     1038FMprintf("ExtValue","deserialize",FMLV_ERROR,"Bad syntax: '%s'",in);
    9501039setEmpty();
    9511040return NULL;
     
    9681057ExtValue ExtValue::getExtType()
    9691058{
    970 if (getType()!=TObj) return ExtValue((paInt)getType());
     1059static const char* typenames[]={"null","int","float","string","","invalid"};
     1060if (getType()!=TObj)
     1061        return ExtValue(typenames[(int)getType()]);
    9711062ExtObject& o=odata();
    9721063return ExtValue(SString(o.isEmpty()?"":o.interfaceName()));
  • cpp/frams/util/extvalue.h

    r326 r333  
    136136        static ExtValue invalid() { ExtValue v; v.setInvalid(); return v; }
    137137        static const ExtValue& empty() { static const ExtValue v; return v; }
    138         int compare(const ExtValue& src) const;
     138        static const ExtValue& zero() { static const ExtValue v(0); return v; }
     139
     140        enum CompareResult
     141        {
     142         ResultLower=-1, ResultEqual=0, ResultHigher=1,
     143         ResultEqualUnordered,
     144         ResultUnequal_RelaxedEqual,
     145         ResultUnequal_RelaxedUnequal,
     146         ResultMismatch_RelaxedUnequal,
     147         ResultMismatch
     148        };
     149        // performs all script value comparisons.
     150        // relaxed comparison (internal use only, not available in scripts) works like regular == with additional null~=0, notnull!~0
     151        // and is used for pseudo-boolean conversion allowing for expressions like "if (null) ..."
     152        CompareResult compare(const ExtValue& src) const;
     153
     154        enum CmpOperator { CmpFIRST,CmpEQ=CmpFIRST,CmpNE,CmpGE,CmpLE,CmpGT,CmpLT,/*relaxed (not)equal*/CmpREQ,CmpRNE };
     155        static const char* cmp_op_names[];
     156        class CmpMessageHandler { public: virtual void cmpMessage(SString& text); };
     157        struct CmpContext { const ExtValue *v1,*v2; CmpMessageHandler *handler; };
     158        static CmpMessageHandler default_cmp_message;
     159        static CmpContext default_cmp_context;
     160        // interpret compare() result, optional context controls error messages
     161        // @return 0=false, 1=true, -1=undefined (null in script)
     162        static int interpretCompare(CmpOperator op,CompareResult result,CmpContext *context=&default_cmp_context);
     163
    139164        int operator==(const ExtValue& src) const;
    140165        void operator+=(const ExtValue& src);
     
    154179        void setInvalid() { setEmpty(); type = TInvalid; }
    155180        bool makeUnique() { return (type == TObj) && odata().makeUnique(); } //< @return false if nothing has changed
    156         ExtPType getType() { return type; }
     181        ExtPType getType() const { return type; }
    157182        void *getObjectTarget(const char* classname, bool warn = true) const;
    158183        void setInt(paInt v) { if (type != TInt) setri(v); else idata() = v; }
Note: See TracChangeset for help on using the changeset viewer.