- Timestamp:
- 03/12/15 04:21:46 (10 years ago)
- Location:
- cpp/frams
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/util/extvalue.cpp
r335 r337 24 24 //this lock only protects against ref.counter corruption caused by concurrent reads. 25 25 //read/write conficts and nonatomicity are handled by BarrierObject (at least in theory ;-)) 26 static pthread_mutex_t extobject_ref_lock =PTHREAD_MUTEX_INITIALIZER;26 static pthread_mutex_t extobject_ref_lock = PTHREAD_MUTEX_INITIALIZER; 27 27 #define REF_LOCK pthread_mutex_lock(&extobject_ref_lock) 28 28 #define REF_UNLOCK pthread_mutex_unlock(&extobject_ref_lock) … … 34 34 void ExtObject::incref() const 35 35 { 36 if (subtype&1)37 { 38 REF_LOCK;39 dbobject->refcount++;40 REF_UNLOCK;36 if (subtype & 1) 37 { 38 REF_LOCK; 39 dbobject->refcount++; 40 REF_UNLOCK; 41 41 } 42 42 } … … 44 44 void ExtObject::decref() const 45 45 { 46 if (subtype&1)47 { 48 REF_LOCK;49 bool destroy=!--dbobject->refcount;50 REF_UNLOCK;51 //another thread can now access the object while we are deleting it52 //but this is not a bug since we only guarantee read/read safety53 if (destroy) delete dbobject;46 if (subtype & 1) 47 { 48 REF_LOCK; 49 bool destroy = !--dbobject->refcount; 50 REF_UNLOCK; 51 //another thread can now access the object while we are deleting it 52 //but this is not a bug since we only guarantee read/read safety 53 if (destroy) delete dbobject; 54 54 } 55 55 } … … 57 57 bool ExtObject::operator==(const ExtObject& src) const 58 58 { 59 if (object!=src.object) return false;60 const char* n1=interfaceName();61 const char* n2=src.interfaceName();62 return (n1==n2) || (strcmp(n1,n2)==0);59 if (object != src.object) return false; 60 const char* n1 = interfaceName(); 61 const char* n2 = src.interfaceName(); 62 return (n1 == n2) || (strcmp(n1, n2) == 0); 63 63 } 64 64 65 65 bool ExtObject::makeUnique() 66 66 { 67 if (!(subtype&1)) return false;68 if (dbobject->refcount==1) return false;69 VectorObject* v=VectorObject::fromObject(*this,false);70 if (v)71 { 72 VectorObject* n=new VectorObject;73 n->data.setSize(n->data.size());74 for(int i=0;i<v->data.size();i++)75 { 76 ExtValue *x=(ExtValue*)v->data(i);77 n->data.set(i,x?new ExtValue(*x):NULL);78 } 79 operator=(n->makeObject());80 return true;81 } 82 return false;67 if (!(subtype & 1)) return false; 68 if (dbobject->refcount == 1) return false; 69 VectorObject* v = VectorObject::fromObject(*this, false); 70 if (v) 71 { 72 VectorObject* n = new VectorObject; 73 n->data.setSize(n->data.size()); 74 for (int i = 0; i < v->data.size(); i++) 75 { 76 ExtValue *x = (ExtValue*)v->data(i); 77 n->data.set(i, x ? new ExtValue(*x) : NULL); 78 } 79 operator=(n->makeObject()); 80 return true; 81 } 82 return false; 83 83 } 84 84 85 85 void* ExtObject::getTarget(const char* classname, bool through_barrier, bool warn) const 86 86 { 87 if (!strcmp(interfaceName(),classname))88 return getTarget();87 if (!strcmp(interfaceName(), classname)) 88 return getTarget(); 89 89 #ifndef NO_BARRIER 90 if (through_barrier)91 { 92 BarrierObject *bo=BarrierObject::fromObject(*this);93 if (bo)94 return bo->getSourceObject().getTarget(classname,true,warn);90 if (through_barrier) 91 { 92 BarrierObject *bo = BarrierObject::fromObject(*this); 93 if (bo) 94 return bo->getSourceObject().getTarget(classname, true, warn); 95 95 } 96 96 #endif 97 97 98 if (warn)99 { 100 FMprintf("ExtValue","getObjectTarget",FMLV_WARN,"%s object expected, %s found",classname,interfaceName());101 } 102 103 return NULL;98 if (warn) 99 { 100 FMprintf("ExtValue", "getObjectTarget", FMLV_WARN, "%s object expected, %s found", classname, interfaceName()); 101 } 102 103 return NULL; 104 104 } 105 105 … … 107 107 SString ExtObject::toString() const 108 108 { 109 if (isEmpty()) return SString("null");110 Param tmp_param;111 ParamInterface *p=getParamInterface(tmp_param);112 int tostr=p->findId("toString");113 if (tostr>=0)114 { 115 return SString(p->getString(tostr));116 } 117 else118 { 119 SString tmp("<");120 tmp+=p->getName();121 tmp+=SString::sprintf(" object at %p>",object?object:paraminterface);122 return tmp;123 } 124 } 125 126 THREAD_LOCAL_DEF(ExtObject::Serialization, ExtObject::serialization);109 if (isEmpty()) return SString("null"); 110 Param tmp_param; 111 ParamInterface *p = getParamInterface(tmp_param); 112 int tostr = p->findId("toString"); 113 if (tostr >= 0) 114 { 115 return SString(p->getString(tostr)); 116 } 117 else 118 { 119 SString tmp("<"); 120 tmp += p->getName(); 121 tmp += SString::sprintf(" object at %p>", object ? object : paraminterface); 122 return tmp; 123 } 124 } 125 126 THREAD_LOCAL_DEF(ExtObject::Serialization, ExtObject::serialization); 127 127 128 128 void ExtObject::Serialization::begin() 129 129 { 130 if (level==0)131 refs.clear();132 level++;130 if (level == 0) 131 refs.clear(); 132 level++; 133 133 } 134 134 135 135 int ExtObject::Serialization::add(const ExtObject &o) 136 136 { 137 if (o.isEmpty()) return -1;138 for(int i=0;i<(int)refs.size();i++)139 { 140 ExtObject& r=refs[i];141 if (r==o) return i;142 } 143 refs.push_back(o);144 return -1;145 } 146 147 void ExtObject::Serialization::replace(const ExtObject& o, const ExtObject& other)148 { 149 if (o.isEmpty()) return;150 for(int i=0;i<(int)refs.size();i++)151 { 152 ExtObject& r=refs[i];153 if (r==o)154 { 155 r=other;156 return;137 if (o.isEmpty()) return -1; 138 for (int i = 0; i < (int)refs.size(); i++) 139 { 140 ExtObject& r = refs[i]; 141 if (r == o) return i; 142 } 143 refs.push_back(o); 144 return -1; 145 } 146 147 void ExtObject::Serialization::replace(const ExtObject& o, const ExtObject& other) 148 { 149 if (o.isEmpty()) return; 150 for (int i = 0; i < (int)refs.size(); i++) 151 { 152 ExtObject& r = refs[i]; 153 if (r == o) 154 { 155 r = other; 156 return; 157 157 } 158 158 } … … 161 161 void ExtObject::Serialization::remove(const ExtObject& o) 162 162 { 163 if (o.isEmpty()) return;164 for(int i=0;i<(int)refs.size();i++)165 { 166 ExtObject& r=refs[i];167 if (o==r) refs.erase(refs.begin()+i);163 if (o.isEmpty()) return; 164 for (int i = 0; i < (int)refs.size(); i++) 165 { 166 ExtObject& r = refs[i]; 167 if (o == r) refs.erase(refs.begin() + i); 168 168 } 169 169 } … … 171 171 const ExtObject* ExtObject::Serialization::get(int ref) 172 172 { 173 if (ref<0) return NULL;174 if (ref>=(int)refs.size()) return NULL;175 return &refs[ref];173 if (ref < 0) return NULL; 174 if (ref >= (int)refs.size()) return NULL; 175 return &refs[ref]; 176 176 } 177 177 178 178 void ExtObject::Serialization::end() 179 179 { 180 level--;181 if (level==0)182 refs.clear();180 level--; 181 if (level == 0) 182 refs.clear(); 183 183 } 184 184 185 185 SString ExtObject::serialize_inner() const 186 186 { 187 int ref=tlsGetRef(serialization).add(*this); 188 if (ref>=0) 189 return SString::sprintf("^%d",ref); 190 191 if (isEmpty()) return SString("null"); 192 VectorObject *vec=VectorObject::fromObject(*this,false); 193 if (vec) 194 return vec->serialize(); 195 DictionaryObject *dic=DictionaryObject::fromObject(*this,false); 196 if (dic) 197 return dic->serialize(); 198 Param tmp_param; 199 ParamInterface *p=getParamInterface(tmp_param); 200 int m=p->findId("toVector"); 201 if (m<0) 202 m=p->findId("toDictionary"); 203 if (m>=0) 204 { 205 ExtObject o(p->getObject(m)); 206 SString ret=SString(interfaceName())+o.serialize(); 187 int ref = tlsGetRef(serialization).add(*this); 188 if (ref >= 0) 189 return SString::sprintf("^%d", ref); 190 191 if (isEmpty()) return SString("null"); 192 VectorObject *vec = VectorObject::fromObject(*this, false); 193 if (vec) 194 return vec->serialize(); 195 DictionaryObject *dic = DictionaryObject::fromObject(*this, false); 196 if (dic) 197 return dic->serialize(); 198 Param tmp_param; 199 ParamInterface *p = getParamInterface(tmp_param); 200 int m = p->findId("toVector"); 201 if (m < 0) 202 m = p->findId("toDictionary"); 203 if (m >= 0) 204 { 205 ExtObject o(p->getObject(m)); 206 SString ret = SString(interfaceName()) + o.serialize(); 207 return ret; 208 } 209 m = p->findId("toString"); 210 if (m >= 0) 211 { 212 SString str = p->getString(m); 213 sstringQuote(str); 214 SString ret = SString(interfaceName()) + "\"" + str + "\""; 215 return ret; 216 } 217 218 tlsGetRef(serialization).remove(*this);//undo nonserializable reference 219 SString ret = interfaceName(); 220 ret += SString::sprintf("<%p>", object ? object : paraminterface); 207 221 return ret; 208 209 m=p->findId("toString"); 210 if (m>=0) 211 212 SString str=p->getString(m);213 sstringQuote(str);214 SString ret=SString(interfaceName())+"\""+str+"\"";222 } 223 224 SString ExtObject::serialize() const 225 { 226 tlsGetRef(serialization).begin(); 227 SString ret = serialize_inner(); 228 tlsGetRef(serialization).end(); 215 229 return ret; 216 }217 218 tlsGetRef(serialization).remove(*this);//undo nonserializable reference219 SString ret=interfaceName();220 ret+=SString::sprintf("<%p>",object?object:paraminterface);221 return ret;222 }223 224 SString ExtObject::serialize() const225 {226 tlsGetRef(serialization).begin();227 SString ret=serialize_inner();228 tlsGetRef(serialization).end();229 return ret;230 230 } 231 231 … … 234 234 SString ExtValue::typeDescription() const 235 235 { 236 switch(type) 237 { 238 case TInt: return SString("integer value"); 239 case TDouble: return SString("floating point value"); 240 case TString: return SString("text string"); 241 case TUnknown: return SString("null value"); 242 case TInvalid: return SString("invalid value"); 243 case TObj: return getObject().isEmpty()?SString("null"):(SString(getObject().interfaceName())+" object"); 244 } 245 return SString::empty(); 246 } 247 248 void *ExtValue::getObjectTarget(const char* classname,bool warn) const 249 { 250 if (type!=TObj) 251 { 252 if (warn) 253 { 254 SString tmp=getString(); 255 if (tmp.len()>30) tmp=tmp.substr(0,30)+"..."; 256 if (type==TString) tmp=SString("\"")+tmp+SString("\""); 257 FMprintf("ExtValue","getObjectTarget",FMLV_WARN,"%s object expected, %s found",classname,(const char*)tmp); 258 } 259 return NULL; 260 } 261 262 return getObject().getTarget(classname,true,warn); 236 switch (type) 237 { 238 case TInt: return SString("int"); 239 case TDouble: return SString("float"); 240 case TString: return SString("string"); 241 case TUnknown: return SString("null"); 242 case TInvalid: return SString("invalid"); 243 case TObj: return getObject().isEmpty() ? SString("null") : SString(getObject().interfaceName()); 244 } 245 return SString::empty(); 246 } 247 248 SString ExtValue::typeAndValue() const 249 { 250 SString msg = typeDescription(); 251 switch (type) 252 { 253 case TInt: case TDouble: case TString: case TObj: 254 msg += " '"; 255 msg += getString(); 256 msg += "'"; 257 default:; 258 } 259 return msg; 260 } 261 262 void *ExtValue::getObjectTarget(const char* classname, bool warn) const 263 { 264 if (type != TObj) 265 { 266 if (warn) 267 { 268 SString tmp = getString(); 269 if (tmp.len() > 30) tmp = tmp.substr(0, 30) + "..."; 270 if (type == TString) tmp = SString("\"") + tmp + SString("\""); 271 FMprintf("ExtValue", "getObjectTarget", FMLV_WARN, "%s object expected, %s found", classname, (const char*)tmp); 272 } 273 return NULL; 274 } 275 276 return getObject().getTarget(classname, true, warn); 263 277 } 264 278 265 279 void ExtValue::set(const ExtValue& src) 266 280 { 267 switch(src.type)281 switch (src.type) 268 282 { 269 283 case TString: sets(src.sdata()); break; … … 271 285 case TDouble: setd(src.ddata()); break; 272 286 case TObj: seto(src.odata()); break; 273 default:type =src.type; break;287 default:type = src.type; break; 274 288 } 275 289 } … … 277 291 void ExtValue::setEmpty() 278 292 { 279 switch(type)293 switch (type) 280 294 { 281 295 #ifdef EXTVALUEUNION … … 288 302 default:; 289 303 } 290 type=TUnknown;304 type = TUnknown; 291 305 } 292 306 293 307 static ExtValue::CompareResult longsign(paInt x) 294 308 { 295 if (x<0) return ExtValue::ResultLower;296 if (x>0) return ExtValue::ResultHigher;297 return ExtValue::ResultEqual;309 if (x < 0) return ExtValue::ResultLower; 310 if (x > 0) return ExtValue::ResultHigher; 311 return ExtValue::ResultEqual; 298 312 } 299 313 300 314 static ExtValue::CompareResult compareNull(const ExtValue& v) 301 315 { 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 strings305 } 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));316 if (v.isNull()) return ExtValue::ResultEqualUnordered; 317 if ((v.getType() == TInt) && (v.getInt() == 0)) return ExtValue::ResultUnequal_RelaxedEqual; 318 return ExtValue::ResultUnequal_RelaxedUnequal; //comparing anything else with null is valid but null is neither higher nor lower than numbers or strings 319 } 320 321 static ExtValue::CompareResult compareFloat(double a, double b) 322 { 323 double t = a - b; 324 if (t < 0) return ExtValue::ResultLower; 325 else if (t > 0) return ExtValue::ResultHigher; 326 return ExtValue::ResultEqual; 327 } 328 329 static ExtValue::CompareResult compareString(const SString &a, const SString &b) 330 { 331 const char* s1 = (const char*)a; 332 const char* s2 = (const char*)b; 333 return longsign(strcmp(s1, s2)); 320 334 } 321 335 322 336 ExtValue::CompareResult ExtValue::compare(const ExtValue& src) const 323 337 { 324 if (isNull())325 return compareNull(src);326 else if (src.isNull())327 return compareNull(*this);328 switch(type)338 if (isNull()) 339 return compareNull(src); 340 else if (src.isNull()) 341 return compareNull(*this); 342 switch (type) 329 343 { 330 344 331 345 case TInt: 332 346 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;} 347 if (src.getType() == TInt) 348 { 349 paInt t = src.getInt(); 350 if (idata() > 0) 351 { 352 if (t > 0) return longsign(idata() - t); else return ResultHigher; 353 } 338 354 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()); 355 { 356 if (t <= 0) return longsign(idata() - t); else return ResultLower; 357 } 358 } 359 else if (src.getType() == TDouble) 360 return compareFloat((double)idata(), src.getDouble()); 343 361 else 344 362 return ResultMismatch;//comparing numbers with other things is invalid … … 346 364 347 365 case TDouble: 348 if ((src.getType() ==TDouble)||(src.getType()==TInt))349 return compareFloat(getDouble(), src.getDouble());366 if ((src.getType() == TDouble) || (src.getType() == TInt)) 367 return compareFloat(getDouble(), src.getDouble()); 350 368 else 351 369 return ResultMismatch; … … 353 371 354 372 case TString: 355 if (src.getType() ==TString)356 return compareString(sdata(), src.getString());373 if (src.getType() == TString) 374 return compareString(sdata(), src.getString()); 357 375 else 358 376 return ResultMismatch; 359 377 break; 360 378 361 case TObj: 362 { 363 if (src.type==TObj) 364 return odata()==src.odata() ? ResultEqualUnordered : ResultUnequal_RelaxedUnequal; 365 if ((src.type==TInt)&&(src.getInt()==0)) 366 return ResultMismatch_RelaxedUnequal; 379 case TObj: 380 { 381 if (src.type == TObj) 382 return odata() == src.odata() ? ResultEqualUnordered : ResultUnequal_RelaxedUnequal; 383 if ((src.type == TInt) && (src.getInt() == 0)) 384 return ResultMismatch_RelaxedUnequal; 385 return ResultMismatch; 386 } 387 default:; 388 } 367 389 return ResultMismatch; 368 } 390 } 391 392 const char* ExtValue::cmp_op_names[] = { "==", "!=", ">=", "<=", ">", "<", "~=", "!~", NULL }; 393 394 int ExtValue::interpretCompare(CmpOperator op, CompareResult result, CmpContext *context) 395 { 396 CompareResult error_threshold = ResultUnequal_RelaxedEqual;//error when ResultUnequal_RelaxedEqual or higher (not comparable) 397 int ret = 0; 398 switch (op) 399 { 400 case CmpEQ: ret = (result == ResultEqual) || (result == ResultEqualUnordered); error_threshold = ResultMismatch_RelaxedUnequal; break; 401 case CmpNE: ret = !((result == ResultEqual) || (result == ResultEqualUnordered)); error_threshold = ResultMismatch_RelaxedUnequal; break; 402 case CmpGT: ret = (result == ResultHigher); error_threshold = ResultEqualUnordered; break; 403 case CmpGE: ret = (result == ResultEqual) || (result == ResultHigher); error_threshold = ResultEqualUnordered; break; 404 case CmpLT: ret = (result == ResultLower); error_threshold = ResultEqualUnordered; break; 405 case CmpLE: ret = (result == ResultEqual) || (result == ResultLower); error_threshold = ResultEqualUnordered; break; 406 case CmpREQ: ret = (result == ResultEqual) || (result == ResultEqualUnordered) || (result == ResultUnequal_RelaxedEqual); error_threshold = ResultMismatch; break; 407 case CmpRNE: ret = !((result == ResultEqual) || (result == ResultEqualUnordered) || (result == ResultUnequal_RelaxedEqual)); error_threshold = ResultMismatch; break; 369 408 default:; 370 409 } 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 CompareResult error_threshold=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); error_threshold=ResultMismatch_RelaxedUnequal; break; 391 case CmpNE: ret=!((result==ResultEqual)||(result==ResultEqualUnordered)); error_threshold=ResultMismatch_RelaxedUnequal; break; 392 case CmpGT: ret=(result==ResultHigher); error_threshold=ResultEqualUnordered; break; 393 case CmpGE: ret=(result==ResultEqual)||(result==ResultHigher); error_threshold=ResultEqualUnordered; break; 394 case CmpLT: ret=(result==ResultLower); error_threshold=ResultEqualUnordered; break; 395 case CmpLE: ret=(result==ResultEqual)||(result==ResultLower); error_threshold=ResultEqualUnordered; break; 396 case CmpREQ: ret=(result==ResultEqual)||(result==ResultEqualUnordered)||(result==ResultUnequal_RelaxedEqual); error_threshold=ResultMismatch; break; 397 case CmpRNE: ret=!((result==ResultEqual)||(result==ResultEqualUnordered)||(result==ResultUnequal_RelaxedEqual)); error_threshold=ResultMismatch; break; 410 if (result >= error_threshold) 411 { 412 SString msg = "Type mismatch while comparing"; 413 if (context) 414 { 415 if (context->v1 && context->v2) 416 msg += SString::sprintf(": %s %s %s", 417 (const char*)context->v1->typeAndValue(), 418 cmp_op_names[op - CmpFIRST], 419 (const char*)context->v2->typeAndValue()); 420 } 421 FMprintf("ExtValue", "interpretCompare", FMLV_ERROR, "%s", (const char*)msg); 422 ret = -1; 423 } 424 return ret; 425 } 426 427 int ExtValue::operator==(const ExtValue& src) const 428 { 429 if (type != src.type) return 0; 430 switch (type) 431 { 432 case TInt: return idata() == src.idata(); 433 case TDouble: return ddata() == src.ddata(); 434 case TString: return sdata() == src.sdata(); 435 case TObj: return odata() == src.odata(); 398 436 default:; 399 437 } 400 if (result >= error_threshold) 401 { 402 if (context) 403 { 404 SString msg="Type mismatch while comparing"; 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; 424 } 425 426 int ExtValue::operator==(const ExtValue& src) const 427 { 428 if (type!=src.type) return 0; 429 switch(type) 430 { 431 case TInt: return idata()==src.idata(); 432 case TDouble: return ddata()==src.ddata(); 433 case TString: return sdata()==src.sdata(); 434 case TObj: return odata()==src.odata(); 438 return 1; 439 } 440 441 void ExtValue::operator+=(const ExtValue& src) 442 { 443 // return = ok, break = fail 444 switch (type) 445 { 446 case TInt: 447 switch (src.getType()) 448 { 449 case TDouble: 450 FMprintf("ExtValue", "add", FMLV_WARN, "Adding %s to %s", (const char*)src.typeAndValue(), (const char*)typeAndValue()); 451 setDouble(double(getInt()) + src.getDouble()); 452 return; 453 case TString: 454 break; 455 default: 456 idata() += src.getInt(); 457 return; 458 } 459 break; 460 case TDouble: 461 switch (src.getType()) 462 { 463 case TString: 464 break; 465 default: 466 ddata() += src.getDouble(); 467 return; 468 } 469 break; 470 case TString: sdata() += src.getString(); return; 471 case TObj: 472 { 473 VectorObject *vec = VectorObject::fromObject(getObject(), false); 474 VectorObject *vec2 = VectorObject::fromObject(src.getObject(), false); 475 if (vec && vec2) 476 { 477 for (int i = 0; i < vec2->data.size(); i++) 478 { 479 ExtValue *s = (ExtValue*)vec2->data(i); 480 ExtValue *d = s ? new ExtValue(*s) : NULL; 481 vec->data += d; 482 } 483 return; 484 } 485 } 486 //NO break; 435 487 default:; 436 488 } 437 return 1; 438 } 439 440 void ExtValue::operator+=(const ExtValue& src) 441 { 442 switch(type) 443 { 444 case TInt: idata()+=src.getInt(); break; 445 case TDouble: ddata()+=src.getDouble(); break; 446 case TString: sdata()+=src.getString(); break; 489 FMprintf("ExtValue", "add", FMLV_ERROR, "Can't add %s to %s", (const char*)src.typeAndValue(), (const char*)typeAndValue()); 490 } 491 492 void ExtValue::operator-=(const ExtValue& src) 493 { 494 // return = ok, break = fail 495 switch (type) 496 { 497 case TInt: 498 switch (src.getType()) 499 { 500 case TInt: 501 idata() -= src.getInt(); 502 return; 503 case TDouble: 504 FMprintf("ExtValue", "subtract", FMLV_WARN, "Subtracting %s from %s", (const char*)src.typeAndValue(), (const char*)typeAndValue()); 505 setDouble(double(getInt()) - src.getDouble()); 506 return; 507 default:; 508 } 509 break; 510 case TDouble: 511 switch (src.getType()) 512 { 513 case TDouble: 514 case TInt: 515 ddata() -= src.getDouble(); 516 return; 517 default:; 518 } 519 break; 520 default:; 521 } 522 FMprintf("ExtValue", "subtract", FMLV_ERROR, "Can't subtract %s from %s", (const char*)src.typeAndValue(), (const char*)typeAndValue()); 523 } 524 525 void ExtValue::operator*=(const ExtValue& src) 526 { 527 // return = ok, break = fail 528 switch (type) 529 { 530 case TInt: 531 switch (src.getType()) 532 { 533 case TInt: 534 idata() *= src.getInt(); 535 return; 536 case TDouble: 537 FMprintf("ExtValue", "multiply", FMLV_WARN, "Multiplying %s by %s", (const char*)typeAndValue(), (const char*)src.typeAndValue()); 538 setDouble(double(getInt())*src.getDouble()); 539 return; 540 default:; 541 } 542 break; 543 case TDouble: 544 switch (src.getType()) 545 { 546 case TInt: 547 case TDouble: 548 ddata() *= src.getDouble(); 549 return; 550 default:; 551 } 552 break; 553 case TString: 554 switch (src.getType()) 555 { 556 case TInt: case TDouble: 557 { 558 SString t; 559 for (int n = src.getInt(); n > 0; n--) 560 t += getString(); 561 setString(t); 562 return; 563 } 564 default:; 565 } 566 break; 447 567 case TObj: 448 { 449 VectorObject *vec=VectorObject::fromObject(getObject(),false); 450 VectorObject *vec2=VectorObject::fromObject(src.getObject(),false); 451 if (vec && vec2) 452 { 453 for(int i=0;i<vec2->data.size();i++) 568 { 569 VectorObject *vec = VectorObject::fromObject(getObject(), false); 570 if (vec) 571 { 572 int n = src.getInt(); 573 int orig_size = vec->data.size(); 574 if (n <= 0) 575 { 576 vec->clear(); return; 577 } 578 for (; n > 1; n--) 579 { 580 for (int i = 0; i < orig_size; i++) 454 581 { 455 ExtValue *s=(ExtValue*)vec2->data(i);456 ExtValue *d=s?new ExtValue(*s):NULL;457 vec->data+=d;582 ExtValue *s = (ExtValue*)vec->data(i); 583 ExtValue *d = s ? new ExtValue(*s) : NULL; 584 vec->data += d; 458 585 } 459 return; 460 } 461 } 586 } 587 return; 588 } 589 } 462 590 //NO break; 463 case TUnknown:464 case TInvalid:465 FMprintf("ExtValue","operator+=",FMLV_WARN,"Can't add %s to %s",(const char*)src.typeDescription(),(const char*)typeDescription());466 591 default:; 467 592 } 468 } 469 470 void ExtValue::operator-=(const ExtValue& src) 471 { 472 switch(type) 473 { 474 case TInt: idata()-=src.getInt(); break; 475 case TDouble: ddata()-=src.getDouble(); break; 476 case TString: case TObj: case TUnknown: case TInvalid: 477 FMprintf("ExtValue","operator-=",FMLV_WARN,"Can't subtract %s from %s",(const char*)src.typeDescription(),(const char*)typeDescription()); 478 break; 479 default:; 480 } 481 } 482 483 void ExtValue::operator*=(const ExtValue& src) 484 { 485 switch(type) 486 { 487 case TInt: idata()*=src.getInt(); break; 488 case TDouble: ddata()*=src.getDouble(); break; 489 case TString: 490 { 491 SString t; 492 for(int n=src.getInt();n>0;n--) 493 t+=getString(); 494 setString(t); 495 break; 496 } 497 case TObj: 498 { 499 VectorObject *vec=VectorObject::fromObject(getObject(),false); 500 if (vec) 501 { 502 int n=src.getInt(); 503 int orig_size=vec->data.size(); 504 if (n<=0) 505 {vec->clear();return;} 506 for(;n>1;n--) 507 { 508 for(int i=0;i<orig_size;i++) 509 { 510 ExtValue *s=(ExtValue*)vec->data(i); 511 ExtValue *d=s?new ExtValue(*s):NULL; 512 vec->data+=d; 513 } 514 } 515 return; 516 } 517 } 518 //NO break; 519 case TUnknown: case TInvalid: 520 FMprintf("ExtValue","operator*=",FMLV_WARN,"Can't multiply %s by %s",(const char*)typeDescription(),(const char*)src.typeDescription()); 521 break; 522 default:; 523 } 593 FMprintf("ExtValue", "multiply", FMLV_WARN, "Can't multiply %s by %s", (const char*)typeAndValue(), (const char*)src.typeAndValue()); 524 594 } 525 595 … … 536 606 } */ 537 607 608 void ExtValue::divInt(paInt a) 609 { 610 if (a) 611 idata() /= a; 612 else 613 { 614 FMprintf("ExtValue", "divide", FMLV_CRITICAL, "Division by zero: %d/0", idata()); 615 setInvalid(); 616 } 617 } 618 619 void ExtValue::divDouble(double a) 620 { 621 if (a == 0.0) 622 { 623 FMprintf("ExtValue", "divide", FMLV_CRITICAL, "Division by zero: %s/0.0", (const char*)getString()); 624 setInvalid(); 625 } 626 else 627 { 628 fpExceptDisable(); 629 double tmp = getDouble() / a; 630 if (!finite(tmp)) 631 { 632 FMprintf("ExtValue", "divide", FMLV_CRITICAL, "Overflow %s/%g", (const char*)getString(), a); setInvalid(); 633 } 634 else 635 setDouble(tmp); 636 // niby dobrze ale lepiej byloby to robic bardziej systematycznie a nie tylko w dzieleniu? 637 //if (isnan(ddata())) //http://www.digitalmars.com/d/archives/c++/Traping_divide_by_zero_5728.html 638 // { FMprintf("ExtValue","divide",FMLV_ERROR,"not-a-number",(const char*)getString()); setInvalid(); } 639 fpExceptEnable(); 640 } 641 } 642 538 643 void ExtValue::operator/=(const ExtValue& src) 539 644 { 540 switch(type)645 switch (type) 541 646 { 542 647 case TInt: 543 { int a=src.getInt(); 544 // idata()/=src.getInt(); 545 if (a) idata()/=a; 546 else {FMprintf("ExtValue","divide",FMLV_CRITICAL,"%d/0",idata()); setInvalid();} 547 } 648 switch (src.getType()) 649 { 650 case TInt: 651 divInt(src.idata()); 652 return; 653 case TDouble: 654 FMprintf("ExtValue", "divide", FMLV_WARN, "Dividing %s by %s", (const char*)typeAndValue(), (const char*)src.typeAndValue()); 655 divDouble(src.ddata()); 656 return; 657 default:; 658 } 548 659 break; 549 660 550 661 case TDouble: 551 { 552 double d=src.getDouble(); 553 if (d==0.0) 554 { 555 FMprintf("ExtValue","divide",FMLV_CRITICAL,"%s/0.0",(const char*)getString()); 556 setInvalid(); 557 } 662 switch (src.getType()) 663 { 664 case TInt: 665 divDouble(src.getDouble()); 666 return; 667 case TDouble: 668 divDouble(src.ddata()); 669 return; 670 default:; 671 } 672 break; 673 674 default:; 675 } 676 FMprintf("ExtValue", "divide", FMLV_ERROR, "Can't divide %s by %s", (const char*)typeAndValue(), (const char*)src.typeAndValue()); 677 } 678 679 SString ExtValue::format(SString& fmt, const ExtValue **values, int count) 680 { 681 SString ret; 682 // "..........%.........%..........%........" 683 // ^_cur ^_next 684 // ^^^^^^^^^^___sub 685 // 686 // "..........%.........%..........%........" 687 // ^-cur ^-next 688 // ^^^^^^^^^^___sub 689 const char* begin = (const char*)fmt, *end = begin + fmt.len(), *curr = begin; 690 int type = 0; 691 692 class Args 693 { 694 const ExtValue **values; 695 int count; 696 int arg; 697 public: 698 Args(const ExtValue **v, int c) :values(v), count(c), arg(0) {} 699 bool finished() { return arg >= count; } 700 const ExtValue *getNext() { const ExtValue *ret = NULL; if ((arg < count) && values[arg]) ret = values[arg]; arg++; return ret; } 701 }; 702 Args args(values, count); 703 704 while (curr < end) 705 { 706 const char* next = strchr(curr, '%'); 707 if (!next) next = end; else if ((next == curr) && (curr > begin)) 708 { 709 next = strchr(next + 1, '%'); if (!next) next = end; 710 } 711 type = 0; 712 if (curr > begin) 713 { 714 type = 0; 715 for (const char* t = curr; t < next; t++) 716 switch (*t) 717 { 718 case 'd': case 'x': case 'X': case 'u': case 'p': case 'c': type = 'd'; t = next; break; 719 case 'f': case 'g': case 'e': type = 'f'; t = next; break; 720 case 's': type = 's'; t = next; break; 721 case 't': case 'T': type = *t; t = next; break; 722 case '%': if (t > begin) { type = *t; t = next; } break; 723 } 724 } 725 if (curr > begin) curr--; 726 const ExtValue *a; 727 if (args.finished() && (type != 0) && (type != '%')) 728 { 729 ret += fmt.substr((int)(curr - begin)); 730 break; 731 } 732 SString sub = fmt.substr((int)(curr - begin), (int)(next - curr)); 733 switch (type) 734 { 735 case 'd': a = args.getNext(); ret += SString::sprintf((const char*)sub, a ? a->getInt() : 0); break; 736 case 'f': a = args.getNext(); ret += SString::sprintf((const char*)sub, a ? a->getDouble() : 0); break; 737 case 's': {a = args.getNext(); SString tmp; if (a) tmp = a->getString(); ret += SString::sprintf((const char*)sub, (const char*)tmp); } break; 738 case 't': case 'T': 739 { 740 a = args.getNext(); 741 time_t ti = a ? a->getInt() : 0; 742 struct tm tm = Convert::localtime(ti); 743 SString timtxt; 744 if (type == 'T') 745 timtxt = SString::sprintf("%04d-%02d-%02d %02d:%02d:%02d", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); 746 else 747 timtxt = Convert::asctime(tm).c_str(); 748 ret += timtxt; 749 ret += sub.substr(2); 750 } 751 break; 752 case '%': ret += '%'; ret += sub.substr(2); break; 753 case 0: ret += sub; break; 754 } 755 curr = next + 1; 756 } 757 return ret; 758 } 759 760 761 void ExtValue::operator%=(const ExtValue& src) 762 { 763 switch (type) 764 { 765 case TInt: idata() = idata() % src.getInt(); break; 766 case TDouble: ddata() = fmod(ddata(), src.getDouble()); break; 767 768 case TString: 769 { 770 VectorObject *vec = VectorObject::fromObject(src.getObject(), false); 771 if (vec) 772 sdata() = format(sdata(), (const ExtValue**)&vec->data.getref(0), vec->data.size()); 558 773 else 559 { 560 fpExceptDisable(); 561 double tmp=ddata()/d; 562 if (!finite(tmp)) 563 { FMprintf("ExtValue","divide",FMLV_CRITICAL,"overflow %s/%s",(const char*)getString(),(const char*)src.getString()); setInvalid(); } 564 else 565 ddata()=tmp; 566 // niby dobrze ale lepiej byloby to robic bardziej systematycznie a nie tylko w dzieleniu? 567 //if (isnan(ddata())) //http://www.digitalmars.com/d/archives/c++/Traping_divide_by_zero_5728.html 568 // { FMprintf("ExtValue","divide",FMLV_ERROR,"not-a-number",(const char*)getString()); setInvalid(); } 569 fpExceptEnable(); 570 } 571 } 572 break; 573 574 case TString: case TObj: case TUnknown: case TInvalid: 575 FMprintf("ExtValue","operator/=",FMLV_WARN,"Can't divide %s by %s",(const char*)typeDescription(),(const char*)src.typeDescription()); 576 break; 577 578 default:; 579 } 580 } 581 582 SString ExtValue::format(SString& fmt,const ExtValue **values,int count) 583 { 584 SString ret; 585 // "..........%.........%..........%........" 586 // ^_cur ^_next 587 // ^^^^^^^^^^___sub 588 // 589 // "..........%.........%..........%........" 590 // ^-cur ^-next 591 // ^^^^^^^^^^___sub 592 const char* begin=(const char*)fmt, *end=begin+fmt.len(), *curr=begin; 593 int type=0; 594 595 class Args 596 { 597 const ExtValue **values; 598 int count; 599 int arg; 600 public: 601 Args(const ExtValue **v,int c):values(v),count(c),arg(0) {} 602 bool finished() {return arg>=count;} 603 const ExtValue *getNext() {const ExtValue *ret=NULL; if ((arg<count)&&values[arg]) ret=values[arg]; arg++; return ret;} 604 }; 605 Args args(values,count); 606 607 while(curr<end) 608 { 609 const char* next=strchr(curr,'%'); 610 if (!next) next=end; else if ((next==curr)&&(curr>begin)) 611 {next=strchr(next+1,'%'); if (!next) next=end;} 612 type=0; 613 if (curr>begin) 614 { 615 type=0; 616 for(const char* t=curr;t<next;t++) 617 switch(*t) 618 { 619 case 'd': case 'x': case 'X': case 'u': case 'p': case 'c': type='d'; t=next; break; 620 case 'f': case 'g': case 'e': type='f'; t=next; break; 621 case 's': type='s'; t=next; break; 622 case 't': case 'T': type=*t; t=next; break; 623 case '%': if (t>begin) {type=*t; t=next;} break; 624 } 625 } 626 if (curr>begin) curr--; 627 const ExtValue *a; 628 if (args.finished() && (type!=0) && (type!='%')) 629 { 630 ret+=fmt.substr((int)(curr-begin)); 631 break; 632 } 633 SString sub=fmt.substr((int)(curr-begin),(int)(next-curr)); 634 switch(type) 635 { 636 case 'd': a=args.getNext(); ret+=SString::sprintf((const char*)sub,a?a->getInt():0); break; 637 case 'f': a=args.getNext(); ret+=SString::sprintf((const char*)sub,a?a->getDouble():0); break; 638 case 's': {a=args.getNext(); SString tmp; if (a) tmp=a->getString(); ret+=SString::sprintf((const char*)sub,(const char*)tmp);} break; 639 case 't': case 'T': 640 { 641 a=args.getNext(); 642 time_t ti=a?a->getInt():0; 643 struct tm tm=Convert::localtime(ti); 644 SString timtxt; 645 if (type=='T') 646 timtxt=SString::sprintf("%04d-%02d-%02d %02d:%02d:%02d",1900+tm.tm_year,1+tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec); 647 else 648 timtxt=Convert::asctime(tm).c_str(); 649 ret+=timtxt; 650 ret+=sub.substr(2); 651 } 652 break; 653 case '%': ret+='%'; ret+=sub.substr(2); break; 654 case 0: ret+=sub; break; 655 } 656 curr=next+1; 657 } 658 return ret; 659 } 660 661 662 void ExtValue::operator%=(const ExtValue& src) 663 { 664 switch(type) 665 { 666 case TInt: idata()=idata()%src.getInt(); break; 667 case TDouble: ddata()=fmod(ddata(),src.getDouble()); break; 668 669 case TString: 670 { 671 VectorObject *vec=VectorObject::fromObject(src.getObject(),false); 672 if (vec) 673 sdata()=format(sdata(),(const ExtValue**)&vec->data.getref(0),vec->data.size()); 674 else 675 {const ExtValue *ptr=&src; sdata()=ExtValue::format(sdata(),&ptr,1);} 676 } 677 break; 774 { 775 const ExtValue *ptr = &src; sdata() = ExtValue::format(sdata(), &ptr, 1); 776 } 777 } 778 break; 678 779 679 780 case TObj: case TUnknown: case TInvalid: 680 FMprintf("ExtValue", "operator%=",FMLV_WARN,"Can't apply modulo to %s",(const char*)typeDescription());781 FMprintf("ExtValue", "modulo", FMLV_WARN, "Can't apply modulo to %s", (const char*)typeDescription()); 681 782 682 783 default:; … … 689 790 const char* after = tmp.parseNumber(s, strict ? TInt : TUnknown); 690 791 if ((after == NULL) || (after[0] != 0)) 691 692 if (error) 693 FMprintf("ExtValue", "parseInt", FMLV_ERROR, "Could not parse '%s'%s", s, strict ?" (strict)":"");792 { 793 if (error) 794 FMprintf("ExtValue", "parseInt", FMLV_ERROR, "Could not parse '%s'%s", s, strict ? " (strict)" : ""); 694 795 return false; 695 796 } 696 797 result = tmp.getInt(); 697 798 return true; … … 703 804 const char* after = tmp.parseNumber(s, TDouble); 704 805 if ((after == NULL) || (after[0] != 0)) 705 706 if (error) 806 { 807 if (error) 707 808 FMprintf("ExtValue", "parseDouble", FMLV_ERROR, "Could not parse '%s'", s); 708 809 return false; 709 810 } 710 811 result = tmp.getDouble(); 711 812 return true; 712 813 } 713 814 714 paInt ExtValue::getInt(const char* s, bool strict)815 paInt ExtValue::getInt(const char* s, bool strict) 715 816 { 716 817 paInt result; … … 780 881 SString ExtValue::serialize() const 781 882 { 782 switch(type)883 switch (type) 783 884 { 784 885 case TString: 785 786 SString q =sdata();886 { 887 SString q = sdata(); 787 888 sstringQuote(q); 788 return SString("\"") +q+SString("\"");789 889 return SString("\"") + q + SString("\""); 890 } 790 891 case TInt: 791 892 return SString::valueOf(idata()); … … 811 912 bool minus = (in[0] == '-'); 812 913 bool plus = (in[0] == '+'); 813 if (((in[0] == '0') && ((in[1] == 'x') || (in[1] =='X')))814 914 if (((in[0] == '0') && ((in[1] == 'x') || (in[1] == 'X'))) 915 || (((minus || plus) && (in[1] == '0') && ((in[2] == 'x') || (in[2] == 'X'))))) 815 916 { 816 917 in += (minus || plus) ? 3 : 2; … … 854 955 PtrListTempl<ParamInterface*> &ExtValue::getDeserializableClasses() 855 956 { 856 static PtrListTempl<ParamInterface*> classes;857 return classes;957 static PtrListTempl<ParamInterface*> classes; 958 return classes; 858 959 } 859 960 860 961 ParamInterface *ExtValue::findDeserializableClass(const char* name) 861 962 { 862 FOREACH(ParamInterface*,cls,getDeserializableClasses())863 if (!strcmp(cls->getName(),name))864 return cls;865 return NULL;963 FOREACH(ParamInterface*, cls, getDeserializableClasses()) 964 if (!strcmp(cls->getName(), name)) 965 return cls; 966 return NULL; 866 967 } 867 968 868 969 static const char* skipWord(const char* in) 869 970 { 870 while(isalpha(*in)||(*in=='_'))871 in++;872 return in;971 while (isalpha(*in) || (*in == '_')) 972 in++; 973 return in; 873 974 } 874 975 … … 876 977 const char* ExtValue::deserialize_inner(const char* in) 877 978 { 878 const char* ret=parseNumber(in); 879 if (ret) 979 const char* ret = parseNumber(in); 980 if (ret) 981 return ret; 982 else if (*in == '\"') 983 { 984 ret = skipQuoteString(in + 1, NULL); 985 SString s(in + 1, (int)(ret - (in + 1))); 986 sstringUnquote(s); 987 setString(s); 988 if (*ret == '\"') 989 return ret + 1; 990 else 991 { 992 FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Missing '\"' in string: '%s'", ret); 993 return NULL; 994 } 995 } 996 else if (*in == '[') 997 { 998 VectorObject *vec = new VectorObject; 999 ExtObject o(&VectorObject::par, vec); 1000 tlsGetRef(ExtObject::serialization).add(o); 1001 const char* p = in + 1; 1002 ExtValue tmp; 1003 while (*p) 1004 { 1005 if (*p == ']') { p++; break; } 1006 ret = tmp.deserialize(p); 1007 if (ret) 1008 { 1009 vec->data += new ExtValue(tmp); 1010 p = ret; 1011 if (*p == ',') p++; 1012 else if (*p != ']') 1013 { 1014 FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Missing ',' in Vector: '%s'", p); 1015 return NULL; 1016 } 1017 } 1018 else 1019 { 1020 p = NULL; 1021 break; 1022 } 1023 } 1024 setObject(o); 1025 return p; 1026 } 1027 else if (*in == '{') 1028 { 1029 DictionaryObject *dic = new DictionaryObject; 1030 ExtObject o(&DictionaryObject::par, dic); 1031 tlsGetRef(ExtObject::serialization).add(o); 1032 const char* p = in + 1; 1033 ExtValue args[2]/*={value,key}*/, dummy_ret; 1034 while (*p) 1035 { 1036 if (*p == '}') { p++; break; } 1037 ret = args[1].deserialize(p); 1038 if ((!ret) || (args[1].getType() != TString)) { p = NULL; break; } 1039 p = ret; 1040 if (*p != ':') { FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Missing ':' in Dictionary: '%s'", p); p = NULL; break; } 1041 p++; 1042 ret = args[0].deserialize(p); 1043 if (!ret) { p = NULL; break; } 1044 p = ret; 1045 dic->p_set(args, &dummy_ret); 1046 if (*p == ',') p++; 1047 else if (*p != '}') 1048 { 1049 FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Missing ',' in Dictionary: '%s'", p); 1050 return NULL; 1051 } 1052 } 1053 setObject(o); 1054 return p; 1055 } 1056 else if (!strncmp(in, "null", 4)) 1057 { 1058 setEmpty(); 1059 return in + 4; 1060 } 1061 else if (!strncmp(in, "invalid", 9)) 1062 { 1063 setInvalid(); 1064 return in + 9; 1065 } 1066 else if (*in == '<') 1067 { //unserializable object 1068 setInvalid(); 1069 while (*in) 1070 if (*in == '>') 1071 return in + 1; 1072 else in++; 1073 return in; 1074 } 1075 else if (*in == '^') 1076 { 1077 in++; 1078 ExtValue ref; 1079 ret = ref.parseNumber(in, TInt); 1080 if (ret && (ref.getType() == TInt)) 1081 { 1082 const ExtObject* o = tlsGetRef(ExtObject::serialization).get(ref.getInt()); 1083 if (o) 1084 { 1085 setObject(*o); 1086 return ret; 1087 } 1088 } 1089 FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Invalid reference: '%s'", in - 1); 1090 return NULL; 1091 } 1092 else if ((ret = skipWord(in)) && (ret != in)) 1093 { 1094 SString clsname(in, (int)(ret - in)); 1095 ExtValue tmp; 1096 ret = tmp.deserialize(ret); 1097 ParamInterface *cls = findDeserializableClass(clsname); 1098 if (cls && (tmp.getType() != TUnknown) && (tmp.getType() != TInvalid)) 1099 { 1100 VectorObject *vec = VectorObject::fromObject(tmp.getObject(), false); 1101 if (vec) 1102 { 1103 int m = cls->findId("newFromVector"); 1104 if (m >= 0) 1105 { 1106 cls->call(m, &tmp, this); 1107 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(), getObject()); 1108 return ret; 1109 } 1110 } 1111 DictionaryObject *dic = DictionaryObject::fromObject(tmp.getObject(), false); 1112 if (dic) 1113 { 1114 int m = cls->findId("newFromDictionary"); 1115 if (m >= 0) 1116 { 1117 cls->call(m, &tmp, this); 1118 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(), getObject()); 1119 return ret; 1120 } 1121 } 1122 if (tmp.getType() == TString) 1123 { 1124 int m = cls->findId("newFromString"); 1125 if (m >= 0) 1126 { 1127 cls->call(m, &tmp, this); 1128 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(), getObject()); 1129 return ret; 1130 } 1131 } 1132 tlsGetRef(ExtObject::serialization).remove(tmp.getObject()); 1133 setEmpty(); 1134 } 1135 setEmpty(); 1136 FMprintf("ExtValue", "deserialize", FMLV_WARN, "object of class \"%s\" could not be deserialized", (const char*)clsname); 1137 return ret; 1138 } 1139 FMprintf("ExtValue", "deserialize", FMLV_ERROR, "Bad syntax: '%s'", in); 1140 setEmpty(); 1141 return NULL; 1142 } 1143 1144 const char* ExtValue::deserialize(const char* in) 1145 { 1146 tlsGetRef(ExtObject::serialization).begin(); 1147 const char* ret = deserialize_inner(in); 1148 tlsGetRef(ExtObject::serialization).end(); 880 1149 return ret; 881 else if (*in=='\"')882 {883 ret=skipQuoteString(in+1,NULL);884 SString s(in+1,(int)(ret-(in+1)));885 sstringUnquote(s);886 setString(s);887 if (*ret=='\"')888 return ret+1;889 else890 {891 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing '\"' in string: '%s'",ret);892 return NULL;893 }894 }895 else if (*in=='[')896 {897 VectorObject *vec=new VectorObject;898 ExtObject o(&VectorObject::par,vec);899 tlsGetRef(ExtObject::serialization).add(o);900 const char* p=in+1;901 ExtValue tmp;902 while(*p)903 {904 if (*p==']') {p++;break;}905 ret=tmp.deserialize(p);906 if (ret)907 {908 vec->data+=new ExtValue(tmp);909 p=ret;910 if (*p==',') p++;911 else if (*p!=']')912 {913 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Vector: '%s'",p);914 return NULL;915 }916 }917 else918 {919 p=NULL;920 break;921 }922 }923 setObject(o);924 return p;925 }926 else if (*in=='{')927 {928 DictionaryObject *dic=new DictionaryObject;929 ExtObject o(&DictionaryObject::par,dic);930 tlsGetRef(ExtObject::serialization).add(o);931 const char* p=in+1;932 ExtValue args[2]/*={value,key}*/, dummy_ret;933 while(*p)934 {935 if (*p=='}') {p++;break;}936 ret=args[1].deserialize(p);937 if ((!ret)||(args[1].getType()!=TString)) {p=NULL;break;}938 p=ret;939 if (*p!=':') {FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ':' in Dictionary: '%s'",p);p=NULL;break;}940 p++;941 ret=args[0].deserialize(p);942 if (!ret) {p=NULL;break;}943 p=ret;944 dic->p_set(args,&dummy_ret);945 if (*p==',') p++;946 else if (*p!='}')947 {948 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Missing ',' in Dictionary: '%s'",p);949 return NULL;950 }951 }952 setObject(o);953 return p;954 }955 else if (!strncmp(in,"null",4))956 {957 setEmpty();958 return in+4;959 }960 else if (!strncmp(in,"invalid",9))961 {962 setInvalid();963 return in+9;964 }965 else if (*in=='<')966 { //unserializable object967 setInvalid();968 while(*in)969 if (*in=='>')970 return in+1;971 else in++;972 return in;973 }974 else if (*in=='^')975 {976 in++;977 ExtValue ref;978 ret=ref.parseNumber(in,TInt);979 if (ret && (ref.getType()==TInt))980 {981 const ExtObject* o=tlsGetRef(ExtObject::serialization).get(ref.getInt());982 if (o)983 {984 setObject(*o);985 return ret;986 }987 }988 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Invalid reference: '%s'",in-1);989 return NULL;990 }991 else if ((ret=skipWord(in))&&(ret!=in))992 {993 SString clsname(in,(int)(ret-in));994 ExtValue tmp;995 ret=tmp.deserialize(ret);996 ParamInterface *cls=findDeserializableClass(clsname);997 if (cls && (tmp.getType()!=TUnknown) && (tmp.getType()!=TInvalid))998 {999 VectorObject *vec=VectorObject::fromObject(tmp.getObject(),false);1000 if (vec)1001 {1002 int m=cls->findId("newFromVector");1003 if (m>=0)1004 {1005 cls->call(m,&tmp,this);1006 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(),getObject());1007 return ret;1008 }1009 }1010 DictionaryObject *dic=DictionaryObject::fromObject(tmp.getObject(),false);1011 if (dic)1012 {1013 int m=cls->findId("newFromDictionary");1014 if (m>=0)1015 {1016 cls->call(m,&tmp,this);1017 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(),getObject());1018 return ret;1019 }1020 }1021 if (tmp.getType()==TString)1022 {1023 int m=cls->findId("newFromString");1024 if (m>=0)1025 {1026 cls->call(m,&tmp,this);1027 tlsGetRef(ExtObject::serialization).replace(tmp.getObject(),getObject());1028 return ret;1029 }1030 }1031 tlsGetRef(ExtObject::serialization).remove(tmp.getObject());1032 setEmpty();1033 }1034 setEmpty();1035 FMprintf("ExtValue","deserialize",FMLV_WARN,"object of class \"%s\" could not be deserialized",(const char*)clsname);1036 return ret;1037 }1038 FMprintf("ExtValue","deserialize",FMLV_ERROR,"Bad syntax: '%s'",in);1039 setEmpty();1040 return NULL;1041 }1042 1043 const char* ExtValue::deserialize(const char* in)1044 {1045 tlsGetRef(ExtObject::serialization).begin();1046 const char* ret=deserialize_inner(in);1047 tlsGetRef(ExtObject::serialization).end();1048 return ret;1049 1150 } 1050 1151 1051 1152 ExtObject ExtValue::getObject() const 1052 1153 { 1053 if (type==TObj) return odata();1054 return ExtObject();1154 if (type == TObj) return odata(); 1155 return ExtObject(); 1055 1156 } 1056 1157 1057 1158 ExtValue ExtValue::getExtType() 1058 1159 { 1059 static const char* typenames[]={"null","int","float","string","","invalid"};1060 if (getType()!=TObj)1061 return ExtValue(typenames[(int)getType()]);1062 ExtObject& o=odata();1063 return ExtValue(SString(o.isEmpty()?"":o.interfaceName()));1160 static const char* typenames[] = { "null", "int", "float", "string", "", "invalid" }; 1161 if (getType() != TObj) 1162 return ExtValue(typenames[(int)getType()]); 1163 ExtObject& o = odata(); 1164 return ExtValue(SString(o.isEmpty() ? "" : o.interfaceName())); 1064 1165 } 1065 1166 1066 1167 SString SString::valueOf(const ExtValue& v) 1067 1168 { 1068 return v.getString();1169 return v.getString(); 1069 1170 } 1070 1171 SString SString::valueOf(const ExtObject& v) 1071 1172 { 1072 return v.toString();1073 } 1173 return v.toString(); 1174 } -
cpp/frams/util/extvalue.h
r333 r337 140 140 enum CompareResult 141 141 { 142 ResultLower=-1, ResultEqual=0, ResultHigher=1,143 144 145 146 147 142 ResultLower = -1, ResultEqual = 0, ResultHigher = 1, 143 ResultEqualUnordered, 144 ResultUnequal_RelaxedEqual, 145 ResultUnequal_RelaxedUnequal, 146 ResultMismatch_RelaxedUnequal, 147 ResultMismatch 148 148 }; 149 149 // performs all script value comparisons. … … 152 152 CompareResult compare(const ExtValue& src) const; 153 153 154 enum CmpOperator { CmpFIRST, CmpEQ=CmpFIRST,CmpNE,CmpGE,CmpLE,CmpGT,CmpLT,/*relaxed (not)equal*/CmpREQ,CmpRNE };154 enum CmpOperator { CmpFIRST, CmpEQ = CmpFIRST, CmpNE, CmpGE, CmpLE, CmpGT, CmpLT,/*relaxed (not)equal*/CmpREQ, CmpRNE }; 155 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; 156 struct CmpContext { const ExtValue *v1, *v2; }; 160 157 // interpret compare() result, optional context controls error messages 161 158 // @return 0=false, 1=true, -1=undefined (null in script) 162 static int interpretCompare(CmpOperator op,CompareResult result,CmpContext *context=&default_cmp_context); 159 static int interpretCompare(CmpOperator op, CompareResult result, CmpContext *context = NULL); 160 161 void divInt(paInt a); 162 void divDouble(double a); 163 163 164 164 int operator==(const ExtValue& src) const; … … 197 197 bool isNull() const { return (type == TUnknown) || ((type == TObj) && odata().isEmpty()); } 198 198 SString typeDescription() const;//< @return human readable type name (used in error messages) 199 SString typeAndValue() const;//< @return type and value (used in error messages) 199 200 const char* parseNumber(const char* in, ExtPType strict_type = TUnknown); 200 201 const char* deserialize(const char* in);//< @return first character after the succesfully parsed string or NULL if failed -
cpp/frams/vm/framscript.y
r333 r337 145 145 { 146 146 #ifdef FRAMSCRIPT_GOTO 147 trctx.out->printf("jump :%s\n",str($2)); FMprintf("FramScriptCompiler","translate",FMLV_WARN,"goto is not recommended (%s line %d)",(const char*)trctx.srcname,trctx.line); trctx.emitLine();147 trctx.out->printf("jump :%s\n",str($2)); FMprintf("FramScriptCompiler","translate",FMLV_WARN,"goto is not recommended"); trctx.emitLine(); 148 148 #else 149 149 trctx.err->printf("goto is not supported\n");return 1; … … 1409 1409 } 1410 1410 1411 class FramscriptCmpMessageHandler: public ExtValue::CmpMessageHandler1412 {1413 public:1414 void cmpMessage(SString& msg)1415 {1416 FMprintf("FramScriptCompiler","translate",FMLV_WARN,"%s (%s line %d)",(const char*)msg,(const char*)trctx.srcname,trctx.line);1417 //trctx.err->printf("%s",(const char*)msg);1418 }1419 };1420 1421 static FramscriptCmpMessageHandler framscript_cmp_messages;1422 1423 1411 bool handleCompare(YYSTYPE& result,const YYSTYPE& arg1,const YYSTYPE& arg2,ExtValue::CmpOperator op,const char* opname) 1424 1412 { … … 1432 1420 context.v1=&arg1; 1433 1421 context.v2=&arg2; 1434 context.handler=&framscript_cmp_messages;1435 1422 int ret=ExtValue::interpretCompare(op,cmp,&context); 1436 1423 if (ret<0) … … 1528 1515 { 1529 1516 if (t.assign && (!t.parens)) 1530 FMprintf("FramScriptCompiler","translate",FMLV_WARN,"Assignment used as truth value, use double parens if you really mean it (%s line %d)",(const char*)trctx.srcname,trctx.line);1517 FMprintf("FramScriptCompiler","translate",FMLV_WARN,"Assignment used as truth value, use ((double parens)) if you really mean it"); 1531 1518 } 1532 1519
Note: See TracChangeset
for help on using the changeset viewer.