Changeset 333 for cpp/frams/util
- Timestamp:
- 03/01/15 01:19:56 (10 years ago)
- Location:
- cpp/frams/util
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/util/extvalue.cpp
r326 r333 13 13 #include <common/Convert.h> 14 14 #include <climits> 15 #include <errno.h> 15 16 16 17 #ifndef NO_BARRIER … … 290 291 } 291 292 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 293 static ExtValue::CompareResult longsign(paInt x) 294 { 295 if (x<0) return ExtValue::ResultLower; 296 if (x>0) return ExtValue::ResultHigher; 297 return ExtValue::ResultEqual; 298 } 299 300 static ExtValue::CompareResult compareNull(const ExtValue& v) 301 { 302 if (v.isNull()) return ExtValue::ResultEqualUnordered; 303 if ((v.getType()==TInt)&&(v.getInt()==0)) return ExtValue::ResultUnequal_RelaxedEqual; 304 return ExtValue::ResultUnequal_RelaxedUnequal; //comparing anything else with null is valid but null is neither higher nor lower than numbers or strings 305 } 306 307 static ExtValue::CompareResult compareFloat(double a,double b) 308 { 309 double t=a-b; 310 if (t<0) return ExtValue::ResultLower; 311 else if (t>0) return ExtValue::ResultHigher; 312 return ExtValue::ResultEqual; 313 } 314 315 static ExtValue::CompareResult compareString(const SString &a,const SString &b) 316 { 317 const char* s1=(const char*)a; 318 const char* s2=(const char*)b; 319 return longsign(strcmp(s1,s2)); 320 } 321 322 ExtValue::CompareResult ExtValue::compare(const ExtValue& src) const 311 323 { 312 324 if (isNull()) … … 316 328 switch(type) 317 329 { 330 318 331 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 326 347 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 333 354 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 341 361 case TObj: 342 362 { 343 363 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; 346 368 } 347 369 default:; 348 370 } 349 return 1; 371 return ResultMismatch; 372 } 373 374 ExtValue::CmpMessageHandler ExtValue::default_cmp_message; 375 ExtValue::CmpContext ExtValue::default_cmp_context={NULL,NULL,&default_cmp_message}; 376 377 const char* ExtValue::cmp_op_names[]={"==","!=",">=","<=",">","<","~=","!~",NULL}; 378 379 void ExtValue::CmpMessageHandler::cmpMessage(SString& text) 380 { 381 FMprintf("ExtValue","interpretCompare",FMLV_ERROR,"%s",(const char*)text); 382 } 383 384 int ExtValue::interpretCompare(CmpOperator op,CompareResult result,CmpContext *context) 385 { 386 int err=ResultUnequal_RelaxedEqual;//error when ResultUnequal_RelaxedEqual or higher (not comparable) 387 int ret=0; 388 switch (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 } 400 if (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 } 423 return ret; 350 424 } 351 425 … … 814 888 return ret+1; 815 889 else 890 { 891 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing '\"' in string: '%s'",ret); 816 892 return NULL; 893 } 817 894 } 818 895 else if (*in=='[') … … 832 909 p=ret; 833 910 if (*p==',') p++; 911 else if (*p!=']') 912 { 913 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Vector: '%s'",p); 914 return NULL; 915 } 834 916 } 835 917 else … … 855 937 if ((!ret)||(args[1].getType()!=TString)) {p=NULL;break;} 856 938 p=ret; 857 if (*p!=':') { p=NULL;break;}939 if (*p!=':') {FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ':' in Dictionary: '%s'",p);p=NULL;break;} 858 940 p++; 859 941 ret=args[0].deserialize(p); … … 862 944 dic->p_set(args,&dummy_ret); 863 945 if (*p==',') p++; 946 else if (*p!='}') 947 { 948 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Dictionary: '%s'",p); 949 return NULL; 950 } 864 951 } 865 952 setObject(o); … … 899 986 } 900 987 } 988 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Invalid reference: '%s'",in-1); 901 989 return NULL; 902 990 } … … 948 1036 return ret; 949 1037 } 1038 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Bad syntax: '%s'",in); 950 1039 setEmpty(); 951 1040 return NULL; … … 968 1057 ExtValue ExtValue::getExtType() 969 1058 { 970 if (getType()!=TObj) return ExtValue((paInt)getType()); 1059 static const char* typenames[]={"null","int","float","string","","invalid"}; 1060 if (getType()!=TObj) 1061 return ExtValue(typenames[(int)getType()]); 971 1062 ExtObject& o=odata(); 972 1063 return ExtValue(SString(o.isEmpty()?"":o.interfaceName())); -
cpp/frams/util/extvalue.h
r326 r333 136 136 static ExtValue invalid() { ExtValue v; v.setInvalid(); return v; } 137 137 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 139 164 int operator==(const ExtValue& src) const; 140 165 void operator+=(const ExtValue& src); … … 154 179 void setInvalid() { setEmpty(); type = TInvalid; } 155 180 bool makeUnique() { return (type == TObj) && odata().makeUnique(); } //< @return false if nothing has changed 156 ExtPType getType() { return type; }181 ExtPType getType() const { return type; } 157 182 void *getObjectTarget(const char* classname, bool warn = true) const; 158 183 void setInt(paInt v) { if (type != TInt) setri(v); else idata() = v; }
Note: See TracChangeset
for help on using the changeset viewer.