00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <list>
00021 #include <algorithm>
00022 #include <pcrecpp.h>
00023 #include <pcre.h>
00024 #include <string.h>
00025 #include <sstream>
00026 #include <iomanip>
00027 #define _USE_MATH_DEFINES
00028 #include <cmath>
00029 #include <limits>
00030
00031 #include "abc.h"
00032 #include "toplevel.h"
00033 #include "flashevents.h"
00034 #include "swf.h"
00035 #include "compat.h"
00036 #include "class.h"
00037 #include "exceptions.h"
00038
00039 using namespace std;
00040 using namespace lightspark;
00041
00042 extern TLSDATA SystemState* sys;
00043
00044 SET_NAMESPACE("");
00045
00046 REGISTER_CLASS_NAME(Array);
00047 REGISTER_CLASS_NAME2(ASQName,"QName","");
00048 REGISTER_CLASS_NAME2(IFunction,"Function","");
00049 REGISTER_CLASS_NAME2(UInteger,"uint","");
00050 REGISTER_CLASS_NAME(Boolean);
00051 REGISTER_CLASS_NAME(Integer);
00052 REGISTER_CLASS_NAME(Number);
00053 REGISTER_CLASS_NAME(Namespace);
00054 REGISTER_CLASS_NAME(Date);
00055 REGISTER_CLASS_NAME(RegExp);
00056 REGISTER_CLASS_NAME(Math);
00057 REGISTER_CLASS_NAME(ASString);
00058 REGISTER_CLASS_NAME2(ASError, "Error", "");
00059 REGISTER_CLASS_NAME(SecurityError);
00060 REGISTER_CLASS_NAME(ArgumentError);
00061 REGISTER_CLASS_NAME(DefinitionError);
00062 REGISTER_CLASS_NAME(EvalError);
00063 REGISTER_CLASS_NAME(RangeError);
00064 REGISTER_CLASS_NAME(ReferenceError);
00065 REGISTER_CLASS_NAME(SyntaxError);
00066 REGISTER_CLASS_NAME(TypeError);
00067 REGISTER_CLASS_NAME(URIError);
00068 REGISTER_CLASS_NAME(VerifyError);
00069
00070 Array::Array()
00071 {
00072 type=T_ARRAY;
00073
00074
00075 }
00076
00077 void Array::sinit(Class_base* c)
00078 {
00079
00080 c->setVariableByQName("CASEINSENSITIVE","",abstract_d(CASEINSENSITIVE));
00081 c->setVariableByQName("DESCENDING","",abstract_d(DESCENDING));
00082 c->setVariableByQName("NUMERIC","",abstract_d(NUMERIC));
00083 c->setVariableByQName("RETURNINDEXEDARRAY","",abstract_d(RETURNINDEXEDARRAY));
00084 c->setVariableByQName("UNIQUESORT","",abstract_d(UNIQUESORT));
00085
00086
00087 c->setGetterByQName("length","",Class<IFunction>::getFunction(_getLength));
00088
00089
00090 c->setConstructor(Class<IFunction>::getFunction(_constructor));
00091 c->setVariableByQName("concat",AS3,Class<IFunction>::getFunction(_concat));
00092
00093 c->setVariableByQName("filter",AS3,Class<IFunction>::getFunction(filter));
00094
00095 c->setVariableByQName("indexOf",AS3,Class<IFunction>::getFunction(indexOf));
00096 c->setVariableByQName("join",AS3,Class<IFunction>::getFunction(join));
00097
00098
00099 c->setVariableByQName("pop",AS3,Class<IFunction>::getFunction(_pop));
00100 c->setVariableByQName("push",AS3,Class<IFunction>::getFunction(_push));
00101
00102 c->setVariableByQName("shift",AS3,Class<IFunction>::getFunction(shift));
00103
00104
00105 c->setVariableByQName("sort",AS3,Class<IFunction>::getFunction(_sort));
00106
00107 c->setVariableByQName("splice",AS3,Class<IFunction>::getFunction(splice));
00108
00109
00110 c->setVariableByQName("unshift",AS3,Class<IFunction>::getFunction(unshift));
00111
00112
00113 c->setVariableByQName("pop","",Class<IFunction>::getFunction(_pop));
00114 }
00115
00116 void Array::buildTraits(ASObject* o)
00117 {
00118 }
00119
00120 ASFUNCTIONBODY(Array,_constructor)
00121 {
00122 Array* th=static_cast<Array*>(obj);
00123
00124 if(argslen==1)
00125 {
00126 int size=args[0]->toInt();
00127 LOG(LOG_CALLS,_("Creating array of length ") << size);
00128 th->resize(size);
00129 }
00130 else
00131 {
00132 LOG(LOG_CALLS,_("Called Array constructor"));
00133 th->resize(argslen);
00134 for(unsigned int i=0;i<argslen;i++)
00135 {
00136 th->set(i,args[i]);
00137 args[i]->incRef();
00138 }
00139 }
00140 return NULL;
00141 }
00142
00143 ASFUNCTIONBODY(Array,_concat)
00144 {
00145 Array* th=static_cast<Array*>(obj);
00146 Array* ret=Class<Array>::getInstanceS();
00147 ret->data=th->data;
00148 if(argslen==1 && args[0]->getObjectType()==T_ARRAY)
00149 {
00150 Array* tmp=Class<Array>::cast(args[0]);
00151 ret->data.insert(ret->data.end(),tmp->data.begin(),tmp->data.end());
00152 }
00153 else
00154 {
00155
00156 ret->data.reserve(ret->data.size()+argslen);
00157 for(unsigned int i=0;i<argslen;i++)
00158 ret->push(args[i]);
00159 }
00160
00161
00162
00163 for(unsigned int i=0;i<ret->data.size();i++)
00164 {
00165 if(ret->data[i].type==DATA_OBJECT)
00166 ret->data[i].data->incRef();
00167 }
00168
00169 return ret;
00170 }
00171
00172 ASFUNCTIONBODY(Array,filter)
00173 {
00174
00175 Array* th=static_cast<Array*>(obj);
00176
00177 LOG(LOG_NOT_IMPLEMENTED,_("Array::filter STUB"));
00178 Array* ret=Class<Array>::getInstanceS();
00179 ret->data=th->data;
00180 for(unsigned int i=0;i<ret->data.size();i++)
00181 {
00182 if(ret->data[i].type==DATA_OBJECT && ret->data[i].data)
00183 ret->data[i].data->incRef();
00184 }
00185 return ret;
00186 }
00187
00188 ASFUNCTIONBODY(Array,_getLength)
00189 {
00190 Array* th=static_cast<Array*>(obj);
00191 return abstract_i(th->data.size());
00192 }
00193
00194 ASFUNCTIONBODY(Array,shift)
00195 {
00196 Array* th=static_cast<Array*>(obj);
00197 if(th->data.empty())
00198 return new Undefined;
00199 ASObject* ret;
00200 if(th->data[0].type==DATA_OBJECT)
00201 ret=th->data[0].data;
00202 else
00203 throw UnsupportedException("Array::shift not completely implemented");
00204 th->data.erase(th->data.begin());
00205 return ret;
00206 }
00207
00208 ASFUNCTIONBODY(Array,splice)
00209 {
00210 Array* th=static_cast<Array*>(obj);
00211
00212 int startIndex=args[0]->toInt();
00213 int deleteCount=args[1]->toUInt();
00214 int totalSize=th->data.size();
00215
00216
00217 assert_and_throw(abs(startIndex)<totalSize);
00218 startIndex=(startIndex+totalSize)%totalSize;
00219 assert_and_throw((startIndex+deleteCount)<=totalSize);
00220
00221 Array* ret=Class<Array>::getInstanceS();
00222 ret->data.reserve(deleteCount);
00223
00224 for(int i=0;i<deleteCount;i++)
00225 ret->data.push_back(th->data[startIndex+i]);
00226
00227 th->data.erase(th->data.begin()+startIndex,th->data.begin()+startIndex+deleteCount);
00228
00229
00230 for(unsigned int i=2,n=0;i<argslen;i++,n++)
00231 {
00232 args[i]->incRef();
00233 th->data.insert(th->data.begin()+startIndex+n,data_slot(args[i]));
00234 }
00235
00236 return ret;
00237 }
00238
00239 ASFUNCTIONBODY(Array,join)
00240 {
00241 Array* th=static_cast<Array*>(obj);
00242 ASObject* del=args[0];
00243 string ret;
00244 for(int i=0;i<th->size();i++)
00245 {
00246 ret+=th->at(i)->toString().raw_buf();
00247 if(i!=th->size()-1)
00248 ret+=del->toString().raw_buf();
00249 }
00250 return Class<ASString>::getInstanceS(ret);
00251 }
00252
00253 ASFUNCTIONBODY(Array,indexOf)
00254 {
00255 Array* th=static_cast<Array*>(obj);
00256 assert_and_throw(argslen==1);
00257 int ret=-1;
00258 ASObject* arg0=args[0];
00259 for(unsigned int i=0;i<th->data.size();i++)
00260 {
00261 assert_and_throw(th->data[i].type==DATA_OBJECT);
00262 if(ABCVm::strictEqualImpl(th->data[i].data,arg0))
00263 {
00264 ret=i;
00265 break;
00266 }
00267 }
00268 return abstract_i(ret);
00269 }
00270
00271
00272 ASFUNCTIONBODY(Array,_pop)
00273 {
00274 Array* th=static_cast<Array*>(obj);
00275 ASObject* ret;
00276 if(th->data.back().type==DATA_OBJECT)
00277 ret=th->data.back().data;
00278 else
00279 throw UnsupportedException("Array::pop not completely implemented");
00280 th->data.pop_back();
00281 return ret;
00282 }
00283
00284 bool Array::sortComparatorDefault::operator()(const data_slot& d1, const data_slot& d2)
00285 {
00286 if(isNumeric)
00287 {
00288 number_t a=numeric_limits<double>::quiet_NaN();
00289 number_t b=numeric_limits<double>::quiet_NaN();
00290 if(d1.type==DATA_INT)
00291 a=d1.data_i;
00292 else if(d1.type==DATA_OBJECT && d1.data)
00293 a=d1.data->toNumber();
00294
00295 if(d2.type==DATA_INT)
00296 b=d2.data_i;
00297 else if(d2.type==DATA_OBJECT && d2.data)
00298 b=d2.data->toNumber();
00299
00300 if(isnan(a) || isnan(b))
00301 throw RunTimeException("Cannot sort non number with Array.NUMERIC option");
00302 return a<b;
00303 }
00304 else
00305 {
00306
00307 tiny_string s1;
00308 tiny_string s2;
00309 if(d1.type==DATA_INT)
00310 s1=tiny_string(d1.data_i);
00311 else if(d1.type==DATA_OBJECT && d1.data)
00312 s1=d1.data->toString();
00313 else
00314 s1="undefined";
00315 if(d2.type==DATA_INT)
00316 s2=tiny_string(d2.data_i);
00317 else if(d2.type==DATA_OBJECT && d2.data)
00318 s2=d2.data->toString();
00319 else
00320 s2="undefined";
00321
00322 return s1<s2;
00323 }
00324 }
00325
00326 bool Array::sortComparatorWrapper::operator()(const data_slot& d1, const data_slot& d2)
00327 {
00328 ASObject* objs[2];
00329 if(d1.type==DATA_INT)
00330 objs[0]=abstract_i(d1.data_i);
00331 else if(d1.type==DATA_OBJECT && d1.data)
00332 {
00333 objs[0]=d1.data;
00334 objs[0]->incRef();
00335 }
00336 else
00337 objs[0]=new Undefined;
00338
00339 if(d2.type==DATA_INT)
00340 objs[1]=abstract_i(d2.data_i);
00341 else if(d2.type==DATA_OBJECT && d2.data)
00342 {
00343 objs[1]=d1.data;
00344 objs[1]->incRef();
00345 }
00346 else
00347 objs[1]=new Undefined;
00348
00349 assert(comparator);
00350 ASObject* ret=comparator->call(new Null, objs, 2);
00351 assert_and_throw(ret);
00352 return (ret->toInt()<0);
00353 }
00354
00355 ASFUNCTIONBODY(Array,_sort)
00356 {
00357 Array* th=static_cast<Array*>(obj);
00358 IFunction* comp=NULL;
00359 bool isNumeric=false;
00360 for(uint32_t i=0;i<argslen;i++)
00361 {
00362 if(args[i]->getObjectType()==T_FUNCTION)
00363 {
00364 assert_and_throw(comp==NULL);
00365 comp=static_cast<IFunction*>(args[i]);
00366 }
00367 else
00368 {
00369 uint32_t options=args[i]->toInt();
00370 if(options&NUMERIC)
00371 isNumeric=true;
00372 if(options&(~NUMERIC))
00373 throw UnsupportedException("Array::sort not completely implemented");
00374 }
00375 }
00376
00377 if(comp)
00378 sort(th->data.begin(),th->data.end(),sortComparatorWrapper(comp));
00379 else
00380 sort(th->data.begin(),th->data.end(),sortComparatorDefault(isNumeric));
00381
00382 obj->incRef();
00383 return obj;
00384 }
00385
00386 ASFUNCTIONBODY(Array,sortOn)
00387 {
00388
00389
00390
00391
00392 obj->incRef();
00393 return obj;
00394 }
00395
00396 ASFUNCTIONBODY(Array,unshift)
00397 {
00398 Array* th=static_cast<Array*>(obj);
00399 for(uint32_t i=0;i<argslen;i++)
00400 {
00401 th->data.insert(th->data.begin(),data_slot(args[i],DATA_OBJECT));
00402 args[i]->incRef();
00403 }
00404 return abstract_i(th->size());;
00405 }
00406
00407 ASFUNCTIONBODY(Array,_push)
00408 {
00409 Array* th=static_cast<Array*>(obj);
00410 for(unsigned int i=0;i<argslen;i++)
00411 {
00412 th->push(args[i]);
00413 args[i]->incRef();
00414 }
00415 return abstract_i(th->size());
00416 }
00417
00418 ASMovieClipLoader::ASMovieClipLoader()
00419 {
00420 }
00421
00422 ASFUNCTIONBODY(ASMovieClipLoader,constructor)
00423 {
00424 LOG(LOG_NOT_IMPLEMENTED,_("Called MovieClipLoader constructor"));
00425 return NULL;
00426 }
00427
00428 ASFUNCTIONBODY(ASMovieClipLoader,addListener)
00429 {
00430 LOG(LOG_NOT_IMPLEMENTED,_("Called MovieClipLoader::addListener"));
00431 return NULL;
00432 }
00433
00434 ASXML::ASXML()
00435 {
00436 xml_buf=new char[1024*20];
00437 xml_index=0;
00438 }
00439
00440 ASFUNCTIONBODY(ASXML,constructor)
00441 {
00442 LOG(LOG_NOT_IMPLEMENTED,_("Called XML constructor"));
00443 return NULL;
00444 }
00445
00446
00447 size_t ASXML::write_data(void *buffer, size_t size, size_t nmemb, void *userp)
00448 {
00449 ASXML* th=(ASXML*)userp;
00450 memcpy(th->xml_buf+th->xml_index,buffer,size*nmemb);
00451 th->xml_index+=size*nmemb;
00452 return size*nmemb;
00453 }
00454
00455 ASFUNCTIONBODY(ASXML,load)
00456 {
00457 LOG(LOG_NOT_IMPLEMENTED,_("Called ASXML::load ") << args[0]->toString());
00458 throw UnsupportedException("ASXML::load not completely implemented");
00459 }
00460
00461 bool Array::isEqual(ASObject* r)
00462 {
00463 assert_and_throw(implEnable);
00464 if(r->getObjectType()!=T_ARRAY)
00465 return false;
00466 else
00467 {
00468 const Array* ra=static_cast<const Array*>(r);
00469 int size=data.size();
00470 if(size!=ra->size())
00471 return false;
00472
00473 for(int i=0;i<size;i++)
00474 {
00475 if(data[i].type!=DATA_OBJECT)
00476 throw UnsupportedException("Array::isEqual not completely implemented");
00477 if(!data[i].data->isEqual(ra->at(i)))
00478 return false;
00479 }
00480 return true;
00481 }
00482 }
00483
00484 intptr_t Array::getVariableByMultiname_i(const multiname& name)
00485 {
00486 assert_and_throw(implEnable);
00487 unsigned int index=0;
00488 if(!isValidMultiname(name,index))
00489 return ASObject::getVariableByMultiname_i(name);
00490
00491 if(index<data.size())
00492 {
00493 switch(data[index].type)
00494 {
00495 case DATA_OBJECT:
00496 {
00497 assert(data[index].data!=NULL);
00498 if(data[index].data->getObjectType()==T_INTEGER)
00499 {
00500 Integer* i=static_cast<Integer*>(data[index].data);
00501 return i->toInt();
00502 }
00503 else if(data[index].data->getObjectType()==T_NUMBER)
00504 {
00505 Number* i=static_cast<Number*>(data[index].data);
00506 return i->toInt();
00507 }
00508 else
00509 throw UnsupportedException("Array::getVariableByMultiname_i not completely implemented");
00510 }
00511 case DATA_INT:
00512 return data[index].data_i;
00513 }
00514 }
00515
00516 return ASObject::getVariableByMultiname_i(name);
00517 }
00518
00519 ASObject* Array::getVariableByMultiname(const multiname& name, bool skip_impl, bool enableOverride, ASObject* base)
00520 {
00521 if(skip_impl || !implEnable)
00522 return ASObject::getVariableByMultiname(name,skip_impl,enableOverride, base);
00523
00524 assert_and_throw(name.ns.size()>0);
00525 if(name.ns[0].name!="")
00526 return ASObject::getVariableByMultiname(name,skip_impl,enableOverride, base);
00527
00528 unsigned int index=0;
00529 if(!isValidMultiname(name,index))
00530 return ASObject::getVariableByMultiname(name,skip_impl,enableOverride, base);
00531
00532 if(index<data.size())
00533 {
00534 ASObject* ret=NULL;
00535 switch(data[index].type)
00536 {
00537 case DATA_OBJECT:
00538 ret=data[index].data;
00539 if(ret==NULL)
00540 {
00541 ret=new Undefined;
00542 data[index].data=ret;
00543 }
00544 break;
00545 case DATA_INT:
00546 ret=abstract_i(data[index].data_i);
00547 ret->fake_decRef();
00548 break;
00549 }
00550 return ret;
00551 }
00552 else
00553 return new Undefined;
00554 }
00555
00556 void Array::setVariableByMultiname_i(const multiname& name, intptr_t value)
00557 {
00558 assert_and_throw(implEnable);
00559 unsigned int index=0;
00560 if(!isValidMultiname(name,index))
00561 {
00562 ASObject::setVariableByMultiname_i(name,value);
00563 return;
00564 }
00565
00566 if(index>=data.capacity())
00567 {
00568
00569 int new_size=imax(index+1,data.size()*2);
00570 data.reserve(new_size);
00571 }
00572 if(index>=data.size())
00573 resize(index+1);
00574
00575 if(data[index].type==DATA_OBJECT && data[index].data)
00576 data[index].data->decRef();
00577 data[index].data_i=value;
00578 data[index].type=DATA_INT;
00579 }
00580
00581 bool Array::isValidMultiname(const multiname& name, unsigned int& index)
00582 {
00583
00584
00585 assert_and_throw(name.ns.size()!=0);
00586 if(name.ns[0].name!="")
00587 return false;
00588
00589 index=0;
00590 int len;
00591 switch(name.name_type)
00592 {
00593
00594 case multiname::NAME_STRING:
00595 len=name.name_s.len();
00596 assert_and_throw(len);
00597 for(int i=0;i<len;i++)
00598 {
00599 if(name.name_s[i]<'0' || name.name_s[i]>'9')
00600 return false;
00601
00602 index*=10;
00603 index+=(name.name_s[i]-'0');
00604 }
00605 break;
00606
00607 case multiname::NAME_INT:
00608 index=name.name_i;
00609 break;
00610 case multiname::NAME_NUMBER:
00611
00612 index=name.name_d;
00613 break;
00614 default:
00615 throw UnsupportedException("Array::isValidMultiname not completely implemented");
00616 }
00617 return true;
00618 }
00619
00620 void Array::setVariableByMultiname(const multiname& name, ASObject* o, bool enableOverride, ASObject* base)
00621 {
00622 assert_and_throw(implEnable);
00623 unsigned int index=0;
00624 if(!isValidMultiname(name,index))
00625 return ASObject::setVariableByMultiname(name,o,enableOverride,base);
00626
00627 if(index>=data.capacity())
00628 {
00629
00630 int new_size=imax(index+1,data.size()*2);
00631 data.reserve(new_size);
00632 }
00633 if(index>=data.size())
00634 resize(index+1);
00635
00636 if(data[index].type==DATA_OBJECT && data[index].data)
00637 data[index].data->decRef();
00638
00639 if(o->getObjectType()==T_INTEGER)
00640 {
00641 Integer* i=static_cast<Integer*>(o);
00642 data[index].data_i=i->val;
00643 data[index].type=DATA_INT;
00644 o->decRef();
00645 }
00646 else
00647 {
00648 data[index].data=o;
00649 data[index].type=DATA_OBJECT;
00650 }
00651 }
00652
00653 bool Array::isValidQName(const tiny_string& name, const tiny_string& ns, unsigned int& index)
00654 {
00655 if(ns!="")
00656 return false;
00657 assert_and_throw(name.len()!=0);
00658 index=0;
00659
00660
00661 for(int i=0;i<name.len();i++)
00662 {
00663 if(!isdigit(name[i]))
00664 return false;
00665
00666 index*=10;
00667 index+=(name[i]-'0');
00668 }
00669 return true;
00670 }
00671
00672 void Array::setVariableByQName(const tiny_string& name, const tiny_string& ns, ASObject* o, bool skip_impl)
00673 {
00674 assert_and_throw(implEnable);
00675 unsigned int index=0;
00676 if(!isValidQName(name,ns,index))
00677 {
00678 ASObject::setVariableByQName(name,ns,o,skip_impl);
00679 return;
00680 }
00681
00682 if(index>=data.capacity())
00683 {
00684
00685 int new_size=imax(index+1,data.size()*2);
00686 data.reserve(new_size);
00687 }
00688 if(index>=data.size())
00689 resize(index+1);
00690
00691 if(data[index].type==DATA_OBJECT && data[index].data)
00692 data[index].data->decRef();
00693
00694 if(o->getObjectType()==T_INTEGER)
00695 {
00696 Integer* i=static_cast<Integer*>(o);
00697 data[index].data_i=i->val;
00698 data[index].type=DATA_INT;
00699 o->decRef();
00700 }
00701 else
00702 {
00703 data[index].data=o;
00704 data[index].type=DATA_OBJECT;
00705 }
00706 }
00707
00708 ASObject* Array::getVariableByQName(const tiny_string& name, const tiny_string& ns, bool skip_impl)
00709 {
00710 assert_and_throw(implEnable);
00711 throw UnsupportedException("Array::getVariableByQName not completely implemented");
00712 return NULL;
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 }
00743
00744 ASString::ASString()
00745 {
00746 type=T_STRING;
00747 }
00748
00749 ASString::ASString(const string& s):data(s)
00750 {
00751 type=T_STRING;
00752 }
00753
00754 ASString::ASString(const tiny_string& s):data(s.raw_buf())
00755 {
00756 type=T_STRING;
00757 }
00758
00759 ASString::ASString(const char* s):data(s)
00760 {
00761 type=T_STRING;
00762 }
00763
00764 ASString::ASString(const char* s, uint32_t len):data(s, len)
00765 {
00766 type=T_STRING;
00767 }
00768
00769 ASFUNCTIONBODY(ASString,_constructor)
00770 {
00771 ASString* th=static_cast<ASString*>(obj);
00772 if(args && args[0])
00773 th->data=args[0]->toString().raw_buf();
00774 return NULL;
00775 }
00776
00777 ASFUNCTIONBODY(ASString,_getLength)
00778 {
00779 ASString* th=static_cast<ASString*>(obj);
00780 return abstract_i(th->data.size());
00781 }
00782
00783 void ASString::sinit(Class_base* c)
00784 {
00785 c->setConstructor(Class<IFunction>::getFunction(_constructor));
00786 c->setVariableByQName("toString","",Class<IFunction>::getFunction(ASObject::_toString));
00787 c->setVariableByQName("split",AS3,Class<IFunction>::getFunction(split));
00788 c->setVariableByQName("substr",AS3,Class<IFunction>::getFunction(substr));
00789 c->setVariableByQName("replace",AS3,Class<IFunction>::getFunction(replace));
00790 c->setVariableByQName("concat",AS3,Class<IFunction>::getFunction(concat));
00791 c->setVariableByQName("match",AS3,Class<IFunction>::getFunction(match));
00792 c->setVariableByQName("search",AS3,Class<IFunction>::getFunction(search));
00793 c->setVariableByQName("indexOf",AS3,Class<IFunction>::getFunction(indexOf));
00794 c->setVariableByQName("charCodeAt",AS3,Class<IFunction>::getFunction(charCodeAt));
00795 c->setVariableByQName("charAt",AS3,Class<IFunction>::getFunction(charAt));
00796 c->setVariableByQName("slice",AS3,Class<IFunction>::getFunction(slice));
00797 c->setVariableByQName("toLowerCase",AS3,Class<IFunction>::getFunction(toLowerCase));
00798 c->setVariableByQName("toUpperCase",AS3,Class<IFunction>::getFunction(toUpperCase));
00799 c->setVariableByQName("fromCharCode",AS3,Class<IFunction>::getFunction(fromCharCode));
00800 c->setGetterByQName("length","",Class<IFunction>::getFunction(_getLength));
00801 }
00802
00803 void ASString::buildTraits(ASObject* o)
00804 {
00805 }
00806
00807 Array::~Array()
00808 {
00809 if(sys && !sys->finalizingDestruction)
00810 {
00811 for(unsigned int i=0;i<data.size();i++)
00812 {
00813 if(data[i].type==DATA_OBJECT && data[i].data)
00814 data[i].data->decRef();
00815 }
00816 }
00817 }
00818
00819 ASFUNCTIONBODY(ASString,search)
00820 {
00821 ASString* th=static_cast<ASString*>(obj);
00822 int ret=-1;
00823 if(args[0]->getPrototype() && args[0]->getPrototype()==Class<RegExp>::getClass())
00824 {
00825 RegExp* re=static_cast<RegExp*>(args[0]);
00826
00827 const char* error;
00828 int errorOffset;
00829 int options=0;
00830 if(re->ignoreCase)
00831 options|=PCRE_CASELESS;
00832 if(re->extended)
00833 options|=PCRE_EXTENDED;
00834 pcre* pcreRE=pcre_compile(re->re.c_str(), 0, &error, &errorOffset,NULL);
00835 if(error)
00836 return abstract_i(ret);
00837
00838 int capturingGroups;
00839 int infoOk=pcre_fullinfo(pcreRE, NULL, PCRE_INFO_CAPTURECOUNT, &capturingGroups);
00840 if(infoOk!=0)
00841 {
00842 pcre_free(pcreRE);
00843 return abstract_i(ret);
00844 }
00845 assert_and_throw(capturingGroups<10);
00846 int ovector[30];
00847 int offset=0;
00848
00849 int rc=pcre_exec(pcreRE, NULL, th->data.c_str(), th->data.size(), offset, 0, ovector, 30);
00850 if(rc<=0)
00851 {
00852
00853 pcre_free(pcreRE);
00854 return abstract_i(ret);
00855 }
00856 ret=ovector[0];
00857 }
00858 else
00859 {
00860 const string& arg0=args[0]->toString().raw_buf();
00861 size_t index=th->data.find(arg0);
00862 if(index!=th->data.npos)
00863 ret=index;
00864 }
00865 return abstract_i(ret);
00866 }
00867
00868 ASFUNCTIONBODY(ASString,match)
00869 {
00870 ASString* th=static_cast<ASString*>(obj);
00871 if(args[0]==NULL || args[0]->getObjectType()==T_NULL || args[0]->getObjectType()==T_UNDEFINED)
00872 return new Null;
00873 Array* ret=NULL;
00874 if(args[0]->getPrototype() && args[0]->getPrototype()==Class<RegExp>::getClass())
00875 {
00876 RegExp* re=static_cast<RegExp*>(args[0]);
00877
00878 const char* error;
00879 int errorOffset;
00880 int options=0;
00881 if(re->ignoreCase)
00882 options|=PCRE_CASELESS;
00883 if(re->extended)
00884 options|=PCRE_EXTENDED;
00885 pcre* pcreRE=pcre_compile(re->re.c_str(), 0, &error, &errorOffset,NULL);
00886 if(error)
00887 return new Null;
00888
00889 int capturingGroups;
00890 int infoOk=pcre_fullinfo(pcreRE, NULL, PCRE_INFO_CAPTURECOUNT, &capturingGroups);
00891 if(infoOk!=0)
00892 {
00893 pcre_free(pcreRE);
00894 return new Null;
00895 }
00896 assert_and_throw(capturingGroups<10);
00897 int ovector[30];
00898 int offset=0;
00899 do
00900 {
00901 int rc=pcre_exec(pcreRE, NULL, th->data.c_str(), th->data.size(), offset, 0, ovector, 30);
00902 if(rc<=0)
00903 {
00904
00905 pcre_free(pcreRE);
00906 if(ret==NULL)
00907 return new Null;
00908 else
00909 return ret;
00910 }
00911 if(ret==NULL)
00912 ret=Class<Array>::getInstanceS();
00913 ret->push(Class<ASString>::getInstanceS(th->data.substr(ovector[0], ovector[1]-ovector[0])));
00914 offset=ovector[1];
00915 }
00916 while(re->global);
00917 }
00918 else
00919 {
00920 ret=Class<Array>::getInstanceS();
00921 const tiny_string& arg0=args[0]->toString();
00922 if(th->data.find(arg0.raw_buf())!=th->data.npos)
00923 ret->push(Class<ASString>::getInstanceS(arg0));
00924 }
00925 return ret;
00926 }
00927
00928 ASFUNCTIONBODY(ASString,split)
00929 {
00930 ASString* th=static_cast<ASString*>(obj);
00931 Array* ret=Class<Array>::getInstanceS();
00932 ASObject* delimiter=args[0];
00933 if(delimiter->getObjectType()==T_UNDEFINED)
00934 {
00935 ret->push(Class<ASString>::getInstanceS(th->data));
00936 return ret;
00937 }
00938
00939 if(args[0]->getPrototype() && args[0]->getPrototype()==Class<RegExp>::getClass())
00940 {
00941 RegExp* re=static_cast<RegExp*>(args[0]);
00942
00943 const char* error;
00944 int offset;
00945 int options=0;
00946 if(re->ignoreCase)
00947 options|=PCRE_CASELESS;
00948 if(re->extended)
00949 options|=PCRE_EXTENDED;
00950 pcre* pcreRE=pcre_compile(re->re.c_str(), 0, &error, &offset,NULL);
00951 if(error)
00952 return ret;
00953
00954 int capturingGroups;
00955 int infoOk=pcre_fullinfo(pcreRE, NULL, PCRE_INFO_CAPTURECOUNT, &capturingGroups);
00956 if(infoOk!=0)
00957 {
00958 pcre_free(pcreRE);
00959 return ret;
00960 }
00961 assert_and_throw(capturingGroups<10);
00962 int ovector[30];
00963 offset=0;
00964 unsigned int end;
00965 do
00966 {
00967 int rc=pcre_exec(pcreRE, NULL, th->data.c_str(), th->data.size(), offset, 0, ovector, 30);
00968 end=ovector[0];
00969 if(rc<=0)
00970 end=th->data.size();
00971 ASString* s=Class<ASString>::getInstanceS(th->data.substr(offset,end-offset));
00972 ret->push(s);
00973 offset=ovector[1];
00974
00975 for(int i=1;i<rc;i++)
00976 {
00977 ASString* s=Class<ASString>::getInstanceS(th->data.substr(ovector[i*2],ovector[i*2+1]-ovector[i*2]));
00978 ret->push(s);
00979 }
00980 }
00981 while(end<th->data.size());
00982 pcre_free(pcreRE);
00983 }
00984 else
00985 {
00986 const tiny_string& del=args[0]->toString();
00987 unsigned int start=0;
00988 do
00989 {
00990 int match=th->data.find(del.raw_buf(),start);
00991 if(del.len()==0)
00992 match++;
00993 if(match==-1)
00994 match=th->data.size();
00995 ASString* s=Class<ASString>::getInstanceS(th->data.substr(start,(match-start)));
00996 ret->push(s);
00997 start=match+del.len();
00998 }
00999 while(start<th->data.size());
01000 }
01001
01002 return ret;
01003 }
01004
01005 ASFUNCTIONBODY(ASString,substr)
01006 {
01007 ASString* th=static_cast<ASString*>(obj);
01008 int start=args[0]->toInt();
01009 if(start<0)
01010 start=th->data.size()+start;
01011
01012 int len=0x7fffffff;
01013 if(argslen==2)
01014 len=args[1]->toInt();
01015
01016 return Class<ASString>::getInstanceS(th->data.substr(start,len));
01017 }
01018
01019 tiny_string Array::toString(bool debugMsg)
01020 {
01021 assert_and_throw(implEnable);
01022 if(debugMsg)
01023 return ASObject::toString(debugMsg);
01024 return toString_priv();
01025 }
01026
01027 tiny_string Array::toString_priv() const
01028 {
01029 string ret;
01030 for(unsigned int i=0;i<data.size();i++)
01031 {
01032 if(data[i].type==DATA_OBJECT)
01033 {
01034 if(data[i].data)
01035 ret+=data[i].data->toString().raw_buf();
01036 }
01037 else if(data[i].type==DATA_INT)
01038 {
01039 char buf[20];
01040 snprintf(buf,20,"%i",data[i].data_i);
01041 ret+=buf;
01042 }
01043 else
01044 throw UnsupportedException("Array::toString not completely implemented");
01045
01046 if(i!=data.size()-1)
01047 ret+=',';
01048 }
01049 return ret;
01050 }
01051
01052 bool Array::nextValue(unsigned int index, ASObject*& out)
01053 {
01054 assert_and_throw(implEnable);
01055 assert_and_throw(index<data.size());
01056 if(data[index].type==DATA_OBJECT)
01057 out=data[index].data;
01058 else if(data[index].type==DATA_INT)
01059 {
01060 out=abstract_i(data[index].data_i);
01061 out->fake_decRef();
01062 }
01063 else
01064 throw UnsupportedException("Unexpeted data type");
01065 return true;
01066 }
01067
01068 bool Array::hasNext(unsigned int& index, bool& out)
01069 {
01070 assert_and_throw(implEnable);
01071 out=index<data.size();
01072 index++;
01073 return true;
01074 }
01075
01076 bool Array::nextName(unsigned int index, ASObject*& out)
01077 {
01078 assert(index>0);
01079 index--;
01080 assert_and_throw(implEnable);
01081 assert_and_throw(index<data.size());
01082 out=abstract_i(index);
01083 return true;
01084 }
01085
01086 void Array::outofbounds() const
01087 {
01088 throw ParseException("Array access out of bounds");
01089 }
01090
01091 tiny_string Boolean::toString(bool debugMsg)
01092 {
01093 return (val)?"true":"false";
01094 }
01095
01096 tiny_string ASString::toString_priv() const
01097 {
01098 return data;
01099 }
01100
01101 tiny_string ASString::toString(bool debugMsg)
01102 {
01103 assert_and_throw(implEnable);
01104 return toString_priv();
01105 }
01106
01107 double ASString::toNumber()
01108 {
01109 assert_and_throw(implEnable);
01110 for(unsigned int i=0;i<data.size();i++)
01111 {
01112 if(!(data[i]>='0' && data[i]<='9' && data[i]!='.'))
01113 return numeric_limits<double>::quiet_NaN();
01114 }
01115 return atof(data.c_str());
01116 }
01117
01118 int32_t ASString::toInt()
01119 {
01120 assert_and_throw(implEnable);
01121 if(data.empty() || !isdigit(data[0]))
01122 return 0;
01123 return atoi(data.c_str());
01124 }
01125
01126 bool ASString::isEqual(ASObject* r)
01127 {
01128 assert_and_throw(implEnable);
01129
01130 if(r->getObjectType()==T_STRING)
01131 {
01132 const ASString* s=static_cast<const ASString*>(r);
01133 return s->data==data;
01134 }
01135 else
01136 return false;
01137 }
01138
01139 TRISTATE ASString::isLess(ASObject* r)
01140 {
01141
01142 assert_and_throw(implEnable);
01143 if(getObjectType()==T_STRING && r->getObjectType()==T_STRING)
01144 {
01145 ASString* rstr=Class<ASString>::cast(r);
01146 return (data<rstr->data)?TTRUE:TFALSE;
01147 }
01148 number_t a=toNumber();
01149 number_t b=r->toNumber();
01150 if(isnan(a) || isnan(b))
01151 return TUNDEFINED;
01152
01153 return (a<b)?TTRUE:TFALSE;
01154 }
01155
01156 bool Boolean::isEqual(ASObject* r)
01157 {
01158 if(r->getObjectType()==T_BOOLEAN)
01159 {
01160 const Boolean* b=static_cast<const Boolean*>(r);
01161 return b->val==val;
01162 }
01163 else
01164 {
01165 return ASObject::isEqual(r);
01166 }
01167 }
01168
01169 Undefined::Undefined()
01170 {
01171 type=T_UNDEFINED;
01172 }
01173
01174 ASFUNCTIONBODY(Undefined,call)
01175 {
01176 LOG(LOG_CALLS,_("Undefined function"));
01177 return NULL;
01178 }
01179
01180 tiny_string Undefined::toString(bool debugMsg)
01181 {
01182 return "undefined";
01183 }
01184
01185 TRISTATE Undefined::isLess(ASObject* r)
01186 {
01187
01188
01189 return TUNDEFINED;
01190 }
01191
01192 bool Undefined::isEqual(ASObject* r)
01193 {
01194 if(r->getObjectType()==T_UNDEFINED)
01195 return true;
01196 if(r->getObjectType()==T_NULL)
01197 return true;
01198 else
01199 return false;
01200 }
01201
01202 int Undefined::toInt()
01203 {
01204 return 0;
01205 }
01206
01207 double Undefined::toNumber()
01208 {
01209 return numeric_limits<double>::quiet_NaN();
01210 }
01211
01212 ASFUNCTIONBODY(Integer,_toString)
01213 {
01214 Integer* th=static_cast<Integer*>(obj);
01215 int radix=10;
01216 char buf[20];
01217 if(argslen==1)
01218 radix=args[0]->toUInt();
01219 assert_and_throw(radix==10 || radix==16);
01220 if(radix==10)
01221 snprintf(buf,20,"%i",th->val);
01222 else if(radix==16)
01223 snprintf(buf,20,"%x",th->val);
01224
01225 return Class<ASString>::getInstanceS(buf);
01226 }
01227
01228 ASFUNCTIONBODY(Integer,generator)
01229 {
01230
01231 return abstract_i(args[0]->toInt()&0xffffffff);
01232 }
01233
01234 TRISTATE Integer::isLess(ASObject* o)
01235 {
01236 switch(o->getObjectType())
01237 {
01238 case T_INTEGER:
01239 {
01240 Integer* i=static_cast<Integer*>(o);
01241 return (val < i->toInt())?TTRUE:TFALSE;
01242 }
01243 break;
01244
01245 case T_NUMBER:
01246 {
01247 Number* i=static_cast<Number*>(o);
01248 return (val < i->toNumber())?TTRUE:TFALSE;
01249 }
01250 break;
01251
01252 case T_STRING:
01253 {
01254 const ASString* s=static_cast<const ASString*>(o);
01255
01256
01257 if(isdigit(s->data[0]))
01258 {
01259 int val2=atoi(s->data.c_str());
01260 return (val < val2)?TTRUE:TFALSE;
01261 }
01262 else
01263 return TFALSE;
01264 }
01265 break;
01266
01267 case T_BOOLEAN:
01268 {
01269 Boolean* i=static_cast<Boolean*>(o);
01270 return (val < i->toInt())?TTRUE:TFALSE;
01271 }
01272 break;
01273
01274 case T_UNDEFINED:
01275 {
01276 return TFALSE;
01277 }
01278 break;
01279
01280 default:
01281 break;
01282 }
01283
01284
01285 return ASObject::isLess(o);
01286 }
01287
01288 bool Integer::isEqual(ASObject* o)
01289 {
01290 if(o->getObjectType()==T_INTEGER)
01291 return val==o->toInt();
01292 else if(o->getObjectType()==T_UINTEGER)
01293 {
01294
01295 return val==o->toInt();
01296 }
01297 else if(o->getObjectType()==T_NUMBER)
01298 return val==o->toInt();
01299 else
01300 {
01301 return ASObject::isEqual(o);
01302 }
01303 }
01304
01305 tiny_string Integer::toString(bool debugMsg)
01306 {
01307 char buf[20];
01308 if(val<0)
01309 {
01310
01311 snprintf(buf,20,"%i",val);
01312 return tiny_string(buf,true);
01313 }
01314 buf[19]=0;
01315 char* cur=buf+19;
01316
01317 int v=val;
01318 do
01319 {
01320 cur--;
01321 *cur='0'+(v%10);
01322 v/=10;
01323 }
01324 while(v!=0);
01325 return tiny_string(cur,true);
01326 }
01327
01328 void Integer::sinit(Class_base* c)
01329 {
01330 c->super=Class<ASObject>::getClass();
01331 c->max_level=c->super->max_level+1;
01332 }
01333
01334 tiny_string UInteger::toString(bool debugMsg)
01335 {
01336 char buf[20];
01337 buf[19]=0;
01338 char* cur=buf+19;
01339
01340 int v=val;
01341 do
01342 {
01343 cur--;
01344 *cur='0'+(v%10);
01345 v/=10;
01346 }
01347 while(v!=0);
01348 return tiny_string(cur,true);
01349 }
01350
01351 TRISTATE UInteger::isLess(ASObject* o)
01352 {
01353 if(o->getObjectType()==T_INTEGER)
01354 {
01355 uint32_t val1=val;
01356 int32_t val2=o->toInt();
01357 if(val2<0)
01358 return TFALSE;
01359 else
01360 return (val1<(uint32_t)val2)?TTRUE:TFALSE;
01361 }
01362 else
01363 throw UnsupportedException("UInteger::isLess is not completely implemented");
01364 }
01365
01366 bool Number::isEqual(ASObject* o)
01367 {
01368 if(o->getObjectType()==T_INTEGER)
01369 return val==o->toNumber();
01370 else if(o->getObjectType()==T_NUMBER)
01371 return val==o->toNumber();
01372 else
01373 {
01374 return ASObject::isEqual(o);
01375 }
01376 }
01377
01378 TRISTATE Number::isLess(ASObject* o)
01379 {
01380 if(o->getObjectType()==T_INTEGER)
01381 {
01382 const Integer* i=static_cast<const Integer*>(o);
01383 return (val<i->val)?TTRUE:TFALSE;
01384 }
01385 else if(o->getObjectType()==T_NUMBER)
01386 {
01387 const Number* i=static_cast<const Number*>(o);
01388 return (val<i->val)?TTRUE:TFALSE;
01389 }
01390 else if(o->getObjectType()==T_UNDEFINED)
01391 {
01392
01393 return TUNDEFINED;
01394 }
01395 else
01396 {
01397 return ASObject::isLess(o);
01398 }
01399 }
01400
01401 tiny_string Number::toString(bool debugMsg)
01402 {
01403 char buf[20];
01404 snprintf(buf,20,"%g",val);
01405 return tiny_string(buf,true);
01406 }
01407
01408 void Number::sinit(Class_base* c)
01409 {
01410 c->super=Class<ASObject>::getClass();
01411 c->max_level=c->super->max_level+1;
01412
01413 Number* ninf=new Number(-numeric_limits<double>::infinity());
01414 Number* pinf=new Number(numeric_limits<double>::infinity());
01415 ninf->setPrototype(c);
01416 pinf->setPrototype(c);
01417 c->setVariableByQName("NEGATIVE_INFINITY","",ninf);
01418 c->setVariableByQName("POSITIVE_INFINITY","",pinf);
01419 }
01420
01421 Date::Date():year(-1),month(-1),date(-1),hour(-1),minute(-1),second(-1),millisecond(-1)
01422 {
01423 }
01424
01425 void Date::sinit(Class_base* c)
01426 {
01427 c->setConstructor(Class<IFunction>::getFunction(_constructor));
01428 c->setVariableByQName("getTimezoneOffset","",Class<IFunction>::getFunction(getTimezoneOffset));
01429 c->setVariableByQName("valueOf","",Class<IFunction>::getFunction(valueOf));
01430 c->setVariableByQName("getTime",AS3,Class<IFunction>::getFunction(getTime));
01431 c->setVariableByQName("getFullYear","",Class<IFunction>::getFunction(getFullYear));
01432 c->setVariableByQName("getHours",AS3,Class<IFunction>::getFunction(getHours));
01433 c->setVariableByQName("getMinutes",AS3,Class<IFunction>::getFunction(getMinutes));
01434 c->setVariableByQName("getSeconds",AS3,Class<IFunction>::getFunction(getMinutes));
01435
01436 }
01437
01438 void Date::buildTraits(ASObject* o)
01439 {
01440 }
01441
01442 ASFUNCTIONBODY(Date,_constructor)
01443 {
01444 Date* th=static_cast<Date*>(obj);
01445 th->year=1969;
01446 th->month=1;
01447 th->date=1;
01448 th->hour=0;
01449 th->minute=0;
01450 th->second=0;
01451 th->millisecond=0;
01452 return NULL;
01453 }
01454
01455 ASFUNCTIONBODY(Date,getTimezoneOffset)
01456 {
01457 LOG(LOG_NOT_IMPLEMENTED,_("getTimezoneOffset"));
01458 return abstract_d(120);
01459 }
01460
01461 ASFUNCTIONBODY(Date,getFullYear)
01462 {
01463 Date* th=static_cast<Date*>(obj);
01464 return abstract_d(th->year);
01465 }
01466
01467 ASFUNCTIONBODY(Date,getHours)
01468 {
01469 Date* th=static_cast<Date*>(obj);
01470 return abstract_d(th->hour);
01471 }
01472
01473 ASFUNCTIONBODY(Date,getMinutes)
01474 {
01475 Date* th=static_cast<Date*>(obj);
01476 return abstract_d(th->minute);
01477 }
01478
01479 ASFUNCTIONBODY(Date,getTime)
01480 {
01481 Date* th=static_cast<Date*>(obj);
01482 return abstract_d(th->toInt());
01483 }
01484
01485 ASFUNCTIONBODY(Date,valueOf)
01486 {
01487 Date* th=static_cast<Date*>(obj);
01488 return abstract_d(th->toInt());
01489 }
01490
01491 bool Date::getIsLeapYear(int year)
01492 {
01493 return ( ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0) );
01494 }
01495
01496 int Date::getDaysInMonth(int month, bool isLeapYear)
01497 {
01498 enum { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
01499
01500 int days;
01501
01502 switch(month)
01503 {
01504 case FEBRUARY:
01505 days = isLeapYear ? 29 : 28;
01506 break;
01507 case JANUARY:
01508 case MARCH:
01509 case MAY:
01510 case JULY:
01511 case AUGUST:
01512 case OCTOBER:
01513 case DECEMBER:
01514 days = 31;
01515 break;
01516 case APRIL:
01517 case JUNE:
01518 case SEPTEMBER:
01519 case NOVEMBER:
01520 days = 30;
01521 break;
01522 default:
01523 days = -1;
01524 }
01525
01526 return days;
01527 }
01528
01529 int Date::toInt()
01530 {
01531 int ret=0;
01532
01533 ret+=((year-1990)*365 + ((year-1989)/4 - (year-1901)/100) + (year-1601)/400)*24*3600*1000;
01534
01535 bool isLeapYear;
01536 for(int j = 1; j < month; j++)
01537 {
01538 isLeapYear = getIsLeapYear(year);
01539 ret+=getDaysInMonth(j, isLeapYear)*24*3600*1000;
01540 }
01541
01542 ret+=(date-1)*24*3600*1000;
01543 ret+=hour*3600*1000;
01544 ret+=minute*60*1000;
01545 ret+=second*1000;
01546 ret+=millisecond;
01547 return ret;
01548 }
01549
01550 tiny_string Date::toString(bool debugMsg)
01551 {
01552 assert_and_throw(implEnable);
01553 return toString_priv();
01554 }
01555
01556 tiny_string Date::toString_priv() const
01557 {
01558 return "Wed Dec 31 16:00:00 GMT-0800 1969";
01559 }
01560
01561 IFunction* SyntheticFunction::toFunction()
01562 {
01563 return this;
01564 }
01565
01566 IFunction* Function::toFunction()
01567 {
01568 return this;
01569 }
01570
01571 IFunction::IFunction():closure_this(NULL),closure_level(-1),bound(false),overriden_by(NULL)
01572 {
01573 type=T_FUNCTION;
01574 }
01575
01576 ASFUNCTIONBODY(IFunction,apply)
01577 {
01578 IFunction* th=static_cast<IFunction*>(obj);
01579 assert_and_throw(argslen==2);
01580
01581
01582 assert_and_throw(args[1]->getObjectType()==T_ARRAY);
01583 Array* array=Class<Array>::cast(args[1]);
01584
01585 int len=array->size();
01586 ASObject** new_args=new ASObject*[len];
01587 for(int i=0;i<len;i++)
01588 {
01589 new_args[i]=array->at(i);
01590 new_args[i]->incRef();
01591 }
01592
01593 args[0]->incRef();
01594 bool overrideThis=true;
01595
01596 if(!(th->closure_this && th->closure_this->prototype && args[0]->prototype && args[0]->prototype->isSubClass(th->closure_this->prototype)) ||
01597 args[0]->prototype==NULL)
01598 {
01599 overrideThis=false;
01600 }
01601 ASObject* ret=th->call(args[0],new_args,len,overrideThis);
01602 delete[] new_args;
01603 return ret;
01604 }
01605
01606 ASFUNCTIONBODY(IFunction,_call)
01607 {
01608 IFunction* th=static_cast<IFunction*>(obj);
01609 assert_and_throw(argslen>=1);
01610 ASObject** new_args=new ASObject*[argslen-1];
01611 for(unsigned int i=1;i<argslen;i++)
01612 {
01613 new_args[i-1]=args[i];
01614 new_args[i-1]->incRef();
01615 }
01616
01617 args[0]->incRef();
01618 bool overrideThis=true;
01619
01620 if(!(th->closure_this && th->closure_this->prototype && args[0]->prototype && args[0]->prototype->isSubClass(th->closure_this->prototype)) ||
01621 args[0]->prototype==NULL)
01622 {
01623 overrideThis=false;
01624 }
01625 ASObject* ret=th->call(args[0],new_args,argslen-1,overrideThis);
01626 delete[] new_args;
01627 return ret;
01628 }
01629
01630 SyntheticFunction::SyntheticFunction(method_info* m):hit_count(0),mi(m),val(NULL)
01631 {
01632
01633 }
01634
01635 ASObject* SyntheticFunction::call(ASObject* obj, ASObject* const* args, uint32_t numArgs, bool thisOverride)
01636 {
01637 const int hit_threshold=10;
01638 if(mi->body==NULL)
01639 {
01640
01641 return NULL;
01642 }
01643
01644
01645 if(sys->useJit && (hit_count==hit_threshold || sys->useInterpreter==false))
01646 {
01647
01648 val=mi->synt_method();
01649 assert_and_throw(val);
01650 }
01651
01652
01653 uint32_t args_len=mi->numArgs();
01654 int passedToLocals=imin(numArgs,args_len);
01655 uint32_t passedToRest=(numArgs > args_len)?(numArgs-mi->numArgs()):0;
01656
01657 int realLevel=(closure_level!=-1)?closure_level:obj->getLevel();
01658
01659 call_context* cc=new call_context(mi,realLevel,args,passedToLocals);
01660 uint32_t i=passedToLocals;
01661 cc->scope_stack=func_scope;
01662 for(unsigned int i=0;i<func_scope.size();i++)
01663 func_scope[i]->incRef();
01664 cc->initialScopeStack=func_scope.size();
01665
01666 if(bound && closure_this && !thisOverride)
01667 {
01668 LOG(LOG_CALLS,_("Calling with closure ") << this);
01669 obj=closure_this;
01670 }
01671
01672 cc->locals[0]=obj;
01673 obj->incRef();
01674
01675
01676 unsigned int missing_params=args_len-i;
01677 assert_and_throw(missing_params<=mi->option_count);
01678 int starting_options=mi->option_count-missing_params;
01679
01680 for(unsigned int j=starting_options;j<mi->option_count;j++)
01681 {
01682 cc->locals[i+1]=mi->getOptional(j);
01683 i++;
01684 }
01685
01686 assert_and_throw(i==args_len);
01687
01688 assert_and_throw(mi->needsArgs()==false || mi->needsRest()==false);
01689 if(mi->needsRest())
01690 {
01691 Array* rest=Class<Array>::getInstanceS();
01692 rest->resize(passedToRest);
01693 for(uint32_t j=0;j<passedToRest;j++)
01694 rest->set(j,args[passedToLocals+j]);
01695
01696 cc->locals[i+1]=rest;
01697 }
01698 else if(mi->needsArgs())
01699 {
01700 Array* argumentsArray=Class<Array>::getInstanceS();
01701 argumentsArray->resize(args_len+passedToRest);
01702 for(uint32_t j=0;j<args_len;j++)
01703 {
01704 cc->locals[j+1]->incRef();
01705 argumentsArray->set(j,cc->locals[j+1]);
01706 }
01707 for(uint32_t j=0;j<passedToRest;j++)
01708 argumentsArray->set(j+args_len,args[passedToLocals+j]);
01709
01710 incRef();
01711 argumentsArray->setVariableByQName("callee","",this);
01712
01713 cc->locals[i+1]=argumentsArray;
01714 }
01715
01716
01717
01718
01719 thisAndLevel tl=getVm()->getCurObjAndLevel();
01720 tl.cur_this->resetLevel();
01721
01722 getVm()->pushObjAndLevel(obj,realLevel);
01723
01724 obj->setLevel(realLevel);
01725
01726 ASObject* ret;
01727 if(val==NULL && sys->useInterpreter)
01728 {
01729
01730 ret=ABCVm::executeFunction(this,cc);
01731 }
01732 else
01733 ret=val(cc);
01734
01735
01736 tl=getVm()->popObjAndLevel();
01737 assert_and_throw(tl.cur_this==obj);
01738 assert_and_throw(tl.cur_this->getLevel()==realLevel);
01739 obj->resetLevel();
01740
01741 tl=getVm()->getCurObjAndLevel();
01742 tl.cur_this->setLevel(tl.cur_level);
01743
01744 delete cc;
01745 hit_count++;
01746 return ret;
01747 }
01748
01749 ASObject* Function::call(ASObject* obj, ASObject* const* args, uint32_t num_args, bool thisOverride)
01750 {
01751 ASObject* ret;
01752 if(bound && closure_this && !thisOverride)
01753 {
01754 LOG(LOG_CALLS,_("Calling with closure ") << this);
01755 obj->decRef();
01756 obj=closure_this;
01757 obj->incRef();
01758 }
01759 ret=val(obj,args,num_args);
01760
01761 for(uint32_t i=0;i<num_args;i++)
01762 args[i]->decRef();
01763 obj->decRef();
01764 return ret;
01765 }
01766
01767 void Math::sinit(Class_base* c)
01768 {
01769
01770 c->setVariableByQName("E","",abstract_d(2.71828182845905));
01771 c->setVariableByQName("LN10","",abstract_d(2.302585092994046));
01772 c->setVariableByQName("LN2","",abstract_d(0.6931471805599453));
01773 c->setVariableByQName(_("LOG10E"),"",abstract_d(0.4342944819032518));
01774 c->setVariableByQName(_("LOG2E"),"",abstract_d(1.442695040888963387));
01775 c->setVariableByQName("PI","",abstract_d(3.141592653589793));
01776 c->setVariableByQName("SQRT1_2","",abstract_d(0.7071067811865476));
01777 c->setVariableByQName("SQRT2","",abstract_d(1.4142135623730951));
01778
01779
01780 c->setVariableByQName("abs","",Class<IFunction>::getFunction(abs));
01781 c->setVariableByQName("acos","",Class<IFunction>::getFunction(acos));
01782 c->setVariableByQName("asin","",Class<IFunction>::getFunction(asin));
01783 c->setVariableByQName("atan","",Class<IFunction>::getFunction(atan));
01784 c->setVariableByQName("atan2","",Class<IFunction>::getFunction(atan2));
01785 c->setVariableByQName("ceil","",Class<IFunction>::getFunction(ceil));
01786 c->setVariableByQName("cos","",Class<IFunction>::getFunction(cos));
01787 c->setVariableByQName("exp","",Class<IFunction>::getFunction(exp));
01788 c->setVariableByQName("floor","",Class<IFunction>::getFunction(floor));
01789 c->setVariableByQName("log","",Class<IFunction>::getFunction(log));
01790 c->setVariableByQName("max","",Class<IFunction>::getFunction(_max));
01791 c->setVariableByQName("min","",Class<IFunction>::getFunction(_min));
01792 c->setVariableByQName("pow","",Class<IFunction>::getFunction(pow));
01793 c->setVariableByQName("random","",Class<IFunction>::getFunction(random));
01794 c->setVariableByQName("round","",Class<IFunction>::getFunction(round));
01795 c->setVariableByQName("sin","",Class<IFunction>::getFunction(sin));
01796 c->setVariableByQName("sqrt","",Class<IFunction>::getFunction(sqrt));
01797 c->setVariableByQName("tan","",Class<IFunction>::getFunction(tan));
01798 }
01799
01800 int Math::hexToInt(char c)
01801 {
01802 if(c>='0' && c<='9')
01803 return c-'0';
01804 else if(c>='a' && c<='f')
01805 return c-'a'+10;
01806 else if(c>='A' && c<='F')
01807 return c-'A'+10;
01808 else
01809 return -1;
01810 }
01811
01812 ASFUNCTIONBODY(Math,atan2)
01813 {
01814 double n1=args[0]->toNumber();
01815 double n2=args[1]->toNumber();
01816 return abstract_d(::atan2(n1,n2));
01817 }
01818
01819 ASFUNCTIONBODY(Math,_max)
01820 {
01821 double largest = args[0]->toNumber();
01822
01823 for(unsigned int i = 1; i < argslen; i++)
01824 {
01825 largest = dmax(largest, args[i]->toNumber());
01826 }
01827
01828 return abstract_d(largest);
01829 }
01830
01831 ASFUNCTIONBODY(Math,_min)
01832 {
01833 double smallest = args[0]->toNumber();
01834
01835 for(unsigned int i = 1; i < argslen; i++)
01836 {
01837 smallest = dmin(smallest, args[i]->toNumber());
01838 }
01839
01840 return abstract_d(smallest);
01841 }
01842
01843 ASFUNCTIONBODY(Math,exp)
01844 {
01845 double n=args[0]->toNumber();
01846 return abstract_d(::exp(n));
01847 }
01848
01849 ASFUNCTIONBODY(Math,acos)
01850 {
01851
01852 double n=args[0]->toNumber();
01853 return abstract_d(::acos(n));
01854 }
01855
01856 ASFUNCTIONBODY(Math,asin)
01857 {
01858
01859 double n=args[0]->toNumber();
01860 return abstract_d(::asin(n));
01861 }
01862
01863 ASFUNCTIONBODY(Math,atan)
01864 {
01865
01866 double n=args[0]->toNumber();
01867 return abstract_d(::atan(n));
01868 }
01869
01870 ASFUNCTIONBODY(Math,cos)
01871 {
01872
01873 double n=args[0]->toNumber();
01874 return abstract_d(::cos(n));
01875 }
01876
01877 ASFUNCTIONBODY(Math,sin)
01878 {
01879
01880 double n=args[0]->toNumber();
01881 return abstract_d(::sin(n));
01882 }
01883
01884 ASFUNCTIONBODY(Math,tan)
01885 {
01886
01887 double n=args[0]->toNumber();
01888 return abstract_d(::tan(n));
01889 }
01890
01891 ASFUNCTIONBODY(Math,abs)
01892 {
01893 double n=args[0]->toNumber();
01894 return abstract_d(::fabs(n));
01895 }
01896
01897 ASFUNCTIONBODY(Math,ceil)
01898 {
01899 double n=args[0]->toNumber();
01900 return abstract_d(::ceil(n));
01901 }
01902
01903 ASFUNCTIONBODY(Math,log)
01904 {
01905 double n=args[0]->toNumber();
01906 return abstract_d(::log(n));
01907 }
01908
01909 ASFUNCTIONBODY(Math,floor)
01910 {
01911 double n=args[0]->toNumber();
01912 return abstract_d(::floor(n));
01913 }
01914
01915 ASFUNCTIONBODY(Math,round)
01916 {
01917 double n=args[0]->toNumber();
01918 return abstract_d(::round(n));
01919 }
01920
01921 ASFUNCTIONBODY(Math,sqrt)
01922 {
01923 double n=args[0]->toNumber();
01924 return abstract_d(::sqrt(n));
01925 }
01926
01927 ASFUNCTIONBODY(Math,pow)
01928 {
01929 double x=args[0]->toNumber();
01930 double y=args[1]->toNumber();
01931 return abstract_d(::pow(x,y));
01932 }
01933
01934 ASFUNCTIONBODY(Math,random)
01935 {
01936 double ret=rand();
01937 ret/=RAND_MAX;
01938 return abstract_d(ret);
01939 }
01940
01941 tiny_string Null::toString(bool debugMsg)
01942 {
01943 return "null";
01944 }
01945
01946 bool Null::isEqual(ASObject* r)
01947 {
01948 if(r->getObjectType()==T_NULL)
01949 return true;
01950 else if(r->getObjectType()==T_UNDEFINED)
01951 return true;
01952 else
01953 return false;
01954 }
01955
01956 RegExp::RegExp():global(false),ignoreCase(false),extended(false),lastIndex(0)
01957 {
01958 }
01959
01960 void RegExp::sinit(Class_base* c)
01961 {
01962 c->setConstructor(Class<IFunction>::getFunction(_constructor));
01963 c->setVariableByQName("exec",AS3,Class<IFunction>::getFunction(exec));
01964 c->setVariableByQName("test",AS3,Class<IFunction>::getFunction(test));
01965 c->setGetterByQName("global","",Class<IFunction>::getFunction(_getGlobal));
01966 }
01967
01968 void RegExp::buildTraits(ASObject* o)
01969 {
01970 }
01971
01972 ASFUNCTIONBODY(RegExp,_constructor)
01973 {
01974 RegExp* th=static_cast<RegExp*>(obj);
01975 th->re=args[0]->toString().raw_buf();
01976 if(argslen>1)
01977 {
01978 const tiny_string& flags=args[1]->toString();
01979 for(int i=0;i<flags.len();i++)
01980 {
01981 switch(flags[i])
01982 {
01983 case 'g':
01984 th->global=true;
01985 break;
01986 case 'i':
01987 th->ignoreCase=true;
01988 break;
01989 case 'x':
01990 th->extended=true;
01991 break;
01992 case 's':
01993 case 'm':
01994 throw UnsupportedException("RegExp not completely implemented");
01995
01996 }
01997 }
01998 }
01999 return NULL;
02000 }
02001
02002 ASFUNCTIONBODY(RegExp,_getGlobal)
02003 {
02004 RegExp* th=static_cast<RegExp*>(obj);
02005 return abstract_b(th->global);
02006 }
02007
02008 ASFUNCTIONBODY(RegExp,exec)
02009 {
02010 RegExp* th=static_cast<RegExp*>(obj);
02011 pcrecpp::RE_Options opt;
02012 opt.set_caseless(th->ignoreCase);
02013 opt.set_extended(th->extended);
02014
02015 pcrecpp::RE pcreRE(th->re,opt);
02016 assert_and_throw(th->lastIndex==0);
02017 const tiny_string& arg0=args[0]->toString();
02018 LOG(LOG_CALLS,_("re: ") << th->re);
02019 int numberOfCaptures=pcreRE.NumberOfCapturingGroups();
02020 LOG(LOG_CALLS,_("capturing groups ") << numberOfCaptures);
02021 assert_and_throw(numberOfCaptures!=-1);
02022
02023 pcrecpp::Arg** captures=new pcrecpp::Arg*[numberOfCaptures];
02024
02025 string* s=new string[numberOfCaptures];
02026 for(int i=0;i<numberOfCaptures;i++)
02027 captures[i]=new pcrecpp::Arg(&s[i]);
02028
02029 int consumed;
02030 bool matched=pcreRE.DoMatch(arg0.raw_buf(),pcrecpp::RE::ANCHOR_START,&consumed,captures,numberOfCaptures);
02031 ASObject* ret;
02032 if(matched)
02033 {
02034 Array* a=Class<Array>::getInstanceS();
02035 for(int i=0;i<numberOfCaptures;i++)
02036 a->push(Class<ASString>::getInstanceS(s[i]));
02037 args[0]->incRef();
02038 a->setVariableByQName("input","",args[0]);
02039 ret=a;
02040
02041 }
02042 else
02043 ret=new Null;
02044
02045 delete[] captures;
02046 delete[] s;
02047
02048 return ret;
02049 }
02050
02051 ASFUNCTIONBODY(RegExp,test)
02052 {
02053 RegExp* th=static_cast<RegExp*>(obj);
02054 pcrecpp::RE_Options opt;
02055 opt.set_caseless(th->ignoreCase);
02056 opt.set_extended(th->extended);
02057
02058 pcrecpp::RE pcreRE(th->re,opt);
02059 assert_and_throw(th->lastIndex==0);
02060 const tiny_string& arg0=args[0]->toString();
02061
02062 bool ret=pcreRE.PartialMatch(arg0.raw_buf());
02063 return abstract_b(ret);
02064 }
02065
02066 ASFUNCTIONBODY(ASString,slice)
02067 {
02068 ASString* th=static_cast<ASString*>(obj);
02069 int startIndex=0;
02070 if(argslen>=1)
02071 startIndex=args[0]->toInt();
02072 int endIndex=0x7fffffff;
02073 if(argslen>=2)
02074 endIndex=args[1]->toInt();
02075 return Class<ASString>::getInstanceS(th->data.substr(startIndex,endIndex));
02076 }
02077
02078 ASFUNCTIONBODY(ASString,charAt)
02079 {
02080 ASString* th=static_cast<ASString*>(obj);
02081 int index=args[0]->toInt();
02082 int maxIndex=th->data.size();
02083 if(index<0 || index>=maxIndex)
02084 return Class<ASString>::getInstanceS();
02085 return Class<ASString>::getInstanceS(th->data.c_str()+index, 1);
02086 }
02087
02088 ASFUNCTIONBODY(ASString,charCodeAt)
02089 {
02090
02091 LOG(LOG_CALLS,_("ASString::charCodeAt not really implemented"));
02092 ASString* th=static_cast<ASString*>(obj);
02093 unsigned int index=args[0]->toInt();
02094 assert_and_throw(index>=0 && index<th->data.size());
02095 return abstract_i(th->data[index]);
02096 }
02097
02098 ASFUNCTIONBODY(ASString,indexOf)
02099 {
02100 ASString* th=static_cast<ASString*>(obj);
02101 const tiny_string& arg0=args[0]->toString();
02102 int startIndex=0;
02103 if(argslen>1)
02104 startIndex=args[1]->toInt();
02105
02106 assert_and_throw(startIndex==0);
02107 bool found=false;
02108 unsigned int i;
02109 for(i=startIndex;i<th->data.size();i++)
02110 {
02111 if(th->data[i]==arg0[0])
02112 {
02113 found=true;
02114 for(int j=1;j<arg0.len();j++)
02115 {
02116 if(th->data[i+j]!=arg0[j])
02117 {
02118 found=false;
02119 break;
02120 }
02121 }
02122 }
02123 if(found)
02124 break;
02125 }
02126
02127 if(!found)
02128 return abstract_i(-1);
02129 else
02130 return abstract_i(i);
02131 }
02132
02133 ASFUNCTIONBODY(ASString,toLowerCase)
02134 {
02135 ASString* th=static_cast<ASString*>(obj);
02136 ASString* ret=Class<ASString>::getInstanceS(th->data);
02137 transform(th->data.begin(), th->data.end(), ret->data.begin(), ::tolower);
02138 return ret;
02139 }
02140
02141 ASFUNCTIONBODY(ASString,toUpperCase)
02142 {
02143 ASString* th=static_cast<ASString*>(obj);
02144 ASString* ret=Class<ASString>::getInstanceS(th->data);
02145 transform(th->data.begin(), th->data.end(), ret->data.begin(), ::toupper);
02146 return ret;
02147 }
02148
02149 ASFUNCTIONBODY(ASString,fromCharCode)
02150 {
02151 assert_and_throw(argslen==1);
02152 int ret=args[0]->toInt();
02153 if(ret>127)
02154 LOG(LOG_NOT_IMPLEMENTED,_("Unicode not supported in String::fromCharCode"));
02155 char buf[2] = { (char)ret, 0 };
02156 return Class<ASString>::getInstanceS(buf);
02157 }
02158
02159 ASFUNCTIONBODY(ASString,replace)
02160 {
02161 ASString* th=static_cast<const ASString*>(obj);
02162 enum REPLACE_TYPE { STRING=0, FUNC };
02163 REPLACE_TYPE type=(args[1]->getObjectType()==T_FUNCTION)?FUNC:STRING;
02164 ASString* ret=Class<ASString>::getInstanceS(th->data);
02165 assert_and_throw(argslen==2);
02166
02167 string replaceWith;
02168 if(type==STRING)
02169 {
02170 replaceWith=args[1]->toString().raw_buf();
02171
02172 assert_and_throw(replaceWith.find('$')==replaceWith.npos);
02173 }
02174
02175 if(args[0]->getPrototype()==Class<RegExp>::getClass())
02176 {
02177 RegExp* re=static_cast<RegExp*>(args[0]);
02178
02179 const char* error;
02180 int errorOffset;
02181 int options=0;
02182 if(re->ignoreCase)
02183 options|=PCRE_CASELESS;
02184 if(re->extended)
02185 options|=PCRE_EXTENDED;
02186 pcre* pcreRE=pcre_compile(re->re.c_str(), 0, &error, &errorOffset,NULL);
02187 if(error)
02188 return ret;
02189
02190 int capturingGroups;
02191 int infoOk=pcre_fullinfo(pcreRE, NULL, PCRE_INFO_CAPTURECOUNT, &capturingGroups);
02192 if(infoOk!=0)
02193 {
02194 pcre_free(pcreRE);
02195 return ret;
02196 }
02197 assert_and_throw(capturingGroups<10);
02198 int ovector[30];
02199 int offset=0;
02200 int retDiff=0;
02201 do
02202 {
02203 int rc=pcre_exec(pcreRE, NULL, ret->data.c_str(), ret->data.size(), offset, 0, ovector, 30);
02204 if(rc<=0)
02205 {
02206
02207 pcre_free(pcreRE);
02208 return ret;
02209 }
02210 if(type==FUNC)
02211 {
02212
02213 IFunction* f=static_cast<IFunction*>(args[1]);
02214 ASObject* subargs[3+capturingGroups];
02215 subargs[0]=Class<ASString>::getInstanceS(ret->data.substr(ovector[0],ovector[1]-ovector[0]));
02216 for(int i=0;i<capturingGroups;i++)
02217 subargs[i+1]=Class<ASString>::getInstanceS(ret->data.substr(ovector[i*2+2],ovector[i*2+3]-ovector[i*2+2]));
02218 subargs[capturingGroups+1]=abstract_i(ovector[0]-retDiff);
02219 th->incRef();
02220 subargs[capturingGroups+2]=th;
02221 ASObject* ret=f->call(new Null, subargs, 3+capturingGroups);
02222 replaceWith=ret->toString().raw_buf();
02223 ret->decRef();
02224 }
02225 ret->data.replace(ovector[0],ovector[1]-ovector[0],replaceWith);
02226 offset=ovector[0]+replaceWith.size();
02227 retDiff+=replaceWith.size()-(ovector[1]-ovector[0]);
02228 }
02229 while(re->global);
02230 }
02231 else
02232 {
02233 const tiny_string& s=args[0]->toString();
02234 int index=ret->data.find(s.raw_buf(),0);
02235 if(index==-1)
02236 return ret;
02237 assert_and_throw(type==STRING);
02238 ret->data.replace(index,s.len(),replaceWith);
02239 }
02240
02241 return ret;
02242 }
02243
02244 ASFUNCTIONBODY(ASString,concat)
02245 {
02246 ASString* th=static_cast<ASString*>(obj);
02247 ASString* ret=Class<ASString>::getInstanceS(th->data);
02248 for(unsigned int i=0;i<argslen;i++)
02249 ret->data+=args[i]->toString().raw_buf();
02250
02251 return ret;
02252 }
02253
02254 ASFUNCTIONBODY(ASError,getStackTrace)
02255 {
02256 ASError* th=static_cast<ASError*>(obj);
02257 ASString* ret=Class<ASString>::getInstanceS(th->toString(true));
02258 LOG(LOG_NOT_IMPLEMENTED,_("Error.getStackTrace not yet implemented."));
02259 return ret;
02260 }
02261
02262 tiny_string ASError::toString(bool debugMsg)
02263 {
02264 return message.len() > 0 ? message : name;
02265 }
02266
02267 ASFUNCTIONBODY(ASError,_getErrorID)
02268 {
02269 ASError* th=static_cast<ASError*>(obj);
02270 return abstract_i(th->errorID);
02271 }
02272
02273 ASFUNCTIONBODY(ASError,_setName)
02274 {
02275 ASError* th=static_cast<ASError*>(obj);
02276 assert_and_throw(argslen==1);
02277 th->name = args[0]->toString();
02278 return NULL;
02279 }
02280
02281 ASFUNCTIONBODY(ASError,_getName)
02282 {
02283 ASError* th=static_cast<ASError*>(obj);
02284 return Class<ASString>::getInstanceS(th->name);
02285 }
02286
02287 ASFUNCTIONBODY(ASError,_setMessage)
02288 {
02289 ASError* th=static_cast<ASError*>(obj);
02290 assert_and_throw(argslen==1);
02291 th->message = args[0]->toString();
02292 return NULL;
02293 }
02294
02295 ASFUNCTIONBODY(ASError,_getMessage)
02296 {
02297 ASError* th=static_cast<ASError*>(obj);
02298 return Class<ASString>::getInstanceS(th->toString(false));
02299 }
02300
02301 ASFUNCTIONBODY(ASError,_constructor)
02302 {
02303 ASError* th=static_cast<ASError*>(obj);
02304 assert_and_throw(argslen <= 2);
02305 if(argslen >= 1)
02306 {
02307 th->message = args[0]->toString();
02308 }
02309 if(argslen == 2)
02310 {
02311 th->errorID = static_cast<Integer*>(args[0])->toInt();
02312 }
02313 return NULL;
02314 }
02315
02316 void ASError::sinit(Class_base* c)
02317 {
02318 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02319 c->setVariableByQName("getStackTrace",AS3,Class<IFunction>::getFunction(getStackTrace));
02320 c->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString));
02321 c->setGetterByQName("errorID","",Class<IFunction>::getFunction(_getErrorID));
02322 c->setGetterByQName("message","",Class<IFunction>::getFunction(_getMessage));
02323 c->setSetterByQName("message","",Class<IFunction>::getFunction(_setMessage));
02324 c->setGetterByQName("name","",Class<IFunction>::getFunction(_getName));
02325 c->setSetterByQName("name","",Class<IFunction>::getFunction(_setName));
02326 }
02327
02328 void ASError::buildTraits(ASObject* o)
02329 {
02330 }
02331
02332 ASFUNCTIONBODY(SecurityError,_constructor)
02333 {
02334 assert(args && argslen<=1);
02335 SecurityError* th=static_cast<SecurityError*>(obj);
02336 if(argslen == 1)
02337 {
02338 th->message = args[0]->toString();
02339 }
02340 return NULL;
02341 }
02342
02343 void SecurityError::sinit(Class_base* c)
02344 {
02345 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02346 c->super=Class<ASError>::getClass();
02347 c->max_level=c->super->max_level+1;
02348 }
02349
02350 void SecurityError::buildTraits(ASObject* o)
02351 {
02352 }
02353
02354 ASFUNCTIONBODY(ArgumentError,_constructor)
02355 {
02356 assert(args && argslen<=1);
02357 ArgumentError* th=static_cast<ArgumentError*>(obj);
02358 if(argslen == 1)
02359 {
02360 th->message = args[0]->toString();
02361 }
02362 return NULL;
02363 }
02364
02365 void ArgumentError::sinit(Class_base* c)
02366 {
02367 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02368 c->super=Class<ASError>::getClass();
02369 c->max_level=c->super->max_level+1;
02370 }
02371
02372 void ArgumentError::buildTraits(ASObject* o)
02373 {
02374 }
02375
02376 ASFUNCTIONBODY(DefinitionError,_constructor)
02377 {
02378 assert(args && argslen<=1);
02379 DefinitionError* th=static_cast<DefinitionError*>(obj);
02380 if(argslen == 1)
02381 {
02382 th->message = args[0]->toString();
02383 }
02384 return NULL;
02385 }
02386
02387 void DefinitionError::sinit(Class_base* c)
02388 {
02389 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02390 c->super=Class<ASError>::getClass();
02391 c->max_level=c->super->max_level+1;
02392 }
02393
02394 void DefinitionError::buildTraits(ASObject* o)
02395 {
02396 }
02397
02398 ASFUNCTIONBODY(EvalError,_constructor)
02399 {
02400 assert(args && argslen<=1);
02401 EvalError* th=static_cast<EvalError*>(obj);
02402 if(argslen == 1)
02403 {
02404 th->message = args[0]->toString();
02405 }
02406 return NULL;
02407 }
02408
02409 void EvalError::sinit(Class_base* c)
02410 {
02411 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02412 c->super=Class<ASError>::getClass();
02413 c->max_level=c->super->max_level+1;
02414 }
02415
02416 void EvalError::buildTraits(ASObject* o)
02417 {
02418 }
02419
02420 ASFUNCTIONBODY(RangeError,_constructor)
02421 {
02422 assert(args && argslen<=1);
02423 RangeError* th=static_cast<RangeError*>(obj);
02424 if(argslen == 1)
02425 {
02426 th->message = args[0]->toString();
02427 }
02428 return NULL;
02429 }
02430
02431 void RangeError::sinit(Class_base* c)
02432 {
02433 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02434 c->super=Class<ASError>::getClass();
02435 c->max_level=c->super->max_level+1;
02436 }
02437
02438 void RangeError::buildTraits(ASObject* o)
02439 {
02440 }
02441
02442 ASFUNCTIONBODY(ReferenceError,_constructor)
02443 {
02444 assert(args && argslen<=1);
02445 ReferenceError* th=static_cast<ReferenceError*>(obj);
02446 if(argslen == 1)
02447 {
02448 th->message = args[0]->toString();
02449 }
02450 return NULL;
02451 }
02452
02453 void ReferenceError::sinit(Class_base* c)
02454 {
02455 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02456 c->super=Class<ASError>::getClass();
02457 c->max_level=c->super->max_level+1;
02458 }
02459
02460 void ReferenceError::buildTraits(ASObject* o)
02461 {
02462 }
02463
02464 ASFUNCTIONBODY(SyntaxError,_constructor)
02465 {
02466 assert(args && argslen<=1);
02467 SyntaxError* th=static_cast<SyntaxError*>(obj);
02468 if(argslen == 1)
02469 {
02470 th->message = args[0]->toString();
02471 }
02472 return NULL;
02473 }
02474
02475 void SyntaxError::sinit(Class_base* c)
02476 {
02477 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02478 c->super=Class<ASError>::getClass();
02479 c->max_level=c->super->max_level+1;
02480 }
02481
02482 void SyntaxError::buildTraits(ASObject* o)
02483 {
02484 }
02485
02486 ASFUNCTIONBODY(TypeError,_constructor)
02487 {
02488 assert(args && argslen<=1);
02489 TypeError* th=static_cast<TypeError*>(obj);
02490 if(argslen == 1)
02491 {
02492 th->message = args[0]->toString();
02493 }
02494 return NULL;
02495 }
02496
02497 void TypeError::sinit(Class_base* c)
02498 {
02499 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02500 c->super=Class<ASError>::getClass();
02501 c->max_level=c->super->max_level+1;
02502 }
02503
02504 void TypeError::buildTraits(ASObject* o)
02505 {
02506 }
02507
02508 ASFUNCTIONBODY(URIError,_constructor)
02509 {
02510 assert(args && argslen<=1);
02511 URIError* th=static_cast<URIError*>(obj);
02512 if(argslen == 1)
02513 {
02514 th->message = args[0]->toString();
02515 }
02516 return NULL;
02517 }
02518
02519 void URIError::sinit(Class_base* c)
02520 {
02521 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02522 c->super=Class<ASError>::getClass();
02523 c->max_level=c->super->max_level+1;
02524 }
02525
02526 void URIError::buildTraits(ASObject* o)
02527 {
02528 }
02529
02530 ASFUNCTIONBODY(VerifyError,_constructor)
02531 {
02532 assert(args && argslen<=1);
02533 VerifyError* th=static_cast<VerifyError*>(obj);
02534 if(argslen == 1)
02535 {
02536 th->message = args[0]->toString();
02537 }
02538 return NULL;
02539 }
02540
02541 void VerifyError::sinit(Class_base* c)
02542 {
02543 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02544 c->super=Class<ASError>::getClass();
02545 c->max_level=c->super->max_level+1;
02546 }
02547
02548 void VerifyError::buildTraits(ASObject* o)
02549 {
02550 }
02551
02552 Class_base::Class_base(const QName& name):use_protected(false),constructor(NULL),referencedObjectsMutex("referencedObjects"),super(NULL),
02553 context(NULL),class_name(name),class_index(-1),max_level(0)
02554 {
02555 type=T_CLASS;
02556 }
02557
02558 Class_base::~Class_base()
02559 {
02560 if(constructor)
02561 constructor->decRef();
02562
02563 if(super)
02564 super->decRef();
02565
02566
02567 if(!referencedObjects.empty())
02568 {
02569 cout << "Class " << class_name << " references " << referencedObjects.size() << endl;
02570 set<ASObject*>::iterator it=referencedObjects.begin();
02571 for(;it!=referencedObjects.end();it++)
02572 delete *it;
02573 }
02574
02575 }
02576
02577 ASObject* Class_base::generator(ASObject* const* args, const unsigned int argslen)
02578 {
02579 return ASObject::generator(NULL, args, argslen);
02580 }
02581
02582 void Class_base::addImplementedInterface(const multiname& i)
02583 {
02584 interfaces.push_back(i);
02585 }
02586
02587 void Class_base::addImplementedInterface(Class_base* i)
02588 {
02589 interfaces_added.push_back(i);
02590 }
02591
02592 tiny_string Class_base::toString(bool debugMsg)
02593 {
02594 tiny_string ret="[Class ";
02595 ret+=class_name.name;
02596 ret+="]";
02597 return ret;
02598 }
02599
02600 void Class_base::recursiveBuild(ASObject* target)
02601 {
02602 if(super)
02603 super->recursiveBuild(target);
02604
02605 LOG(LOG_TRACE,_("Building traits for ") << class_name);
02606 target->setLevel(max_level);
02607 buildInstanceTraits(target);
02608 }
02609
02610 void Class_base::setConstructor(IFunction* c)
02611 {
02612 assert_and_throw(constructor==NULL);
02613 constructor=c;
02614 }
02615
02616 void Class_base::handleConstruction(ASObject* target, ASObject* const* args, unsigned int argslen, bool buildAndLink)
02617 {
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628 if(buildAndLink)
02629 {
02630 #ifndef NDEBUG
02631 assert_and_throw(!target->initialized);
02632 #endif
02633
02634 bool bak=target->implEnable;
02635 target->implEnable=false;
02636 recursiveBuild(target);
02637
02638 target->implEnable=bak;
02639 assert_and_throw(target->getLevel()==max_level);
02640 #ifndef NDEBUG
02641 target->initialized=true;
02642 #endif
02643 }
02644
02645
02646 assert_and_throw(max_level==target->getLevel());
02647 if(constructor)
02648 {
02649 LOG(LOG_CALLS,_("Calling Instance init ") << class_name);
02650 target->incRef();
02651 ASObject* ret=constructor->call(target,args,argslen);
02652 assert_and_throw(ret==NULL);
02653 }
02654 }
02655
02656 void Class_base::acquireObject(ASObject* ob)
02657 {
02658 Locker l(referencedObjectsMutex);
02659 bool ret=referencedObjects.insert(ob).second;
02660 assert_and_throw(ret);
02661 }
02662
02663 void Class_base::abandonObject(ASObject* ob)
02664 {
02665 Locker l(referencedObjectsMutex);
02666 set<ASObject>::size_type ret=referencedObjects.erase(ob);
02667 if(ret!=1)
02668 {
02669 LOG(LOG_ERROR,_("Failure in reference counting"));
02670 }
02671 }
02672
02673 void Class_base::cleanUp()
02674 {
02675 Variables.destroyContents();
02676 if(constructor)
02677 {
02678 constructor->decRef();
02679 constructor=NULL;
02680 }
02681
02682 if(super)
02683 {
02684 super->decRef();
02685 super=NULL;
02686 }
02687 }
02688
02689 ASObject* Class_inherit::getInstance(bool construct, ASObject* const* args, const unsigned int argslen)
02690 {
02691 ASObject* ret=NULL;
02692 if(tag)
02693 {
02694 ret=tag->instance();
02695 assert_and_throw(ret);
02696 }
02697 else
02698 {
02699 assert_and_throw(super);
02700
02701 ret=super->getInstance(false,NULL,0);
02702 }
02703
02704 ret->setPrototype(this);
02705 if(construct)
02706 handleConstruction(ret,args,argslen,true);
02707 return ret;
02708 }
02709
02710 void Class_inherit::buildInstanceTraits(ASObject* o) const
02711 {
02712 assert_and_throw(class_index!=-1);
02713
02714 LOG(LOG_CALLS,_("Building instance traits"));
02715
02716 context->buildInstanceTraits(o,class_index);
02717 }
02718
02719 Class_object* Class_object::getClass()
02720 {
02721
02722
02723 std::map<QName, Class_base*>::iterator it=sys->classes.find(QName("Class",""));
02724 Class_object* ret=NULL;
02725 if(it==sys->classes.end())
02726 {
02727 ret=new Class_object();
02728 sys->classes.insert(std::make_pair(QName("Class",""),ret));
02729 }
02730 else
02731 ret=static_cast<Class_object*>(it->second);
02732
02733 ret->incRef();
02734 return ret;
02735 }
02736
02737 void IFunction::sinit(Class_base* c)
02738 {
02739 c->setVariableByQName("call",AS3,Class<IFunction>::getFunction(IFunction::_call));
02740 c->setVariableByQName("apply",AS3,Class<IFunction>::getFunction(IFunction::apply));
02741 }
02742
02743 Class_function* Class_function::getClass()
02744 {
02745
02746
02747 std::map<QName, Class_base*>::iterator it=sys->classes.find(QName("Function",""));
02748 Class_function* ret=NULL;
02749 if(it==sys->classes.end())
02750 {
02751 ret=new Class_function();
02752 sys->classes.insert(std::make_pair(QName("Function",""),ret));
02753 }
02754 else
02755 ret=static_cast<Class_function*>(it->second);
02756
02757 ret->incRef();
02758 return ret;
02759 }
02760
02761 const std::vector<Class_base*>& Class_base::getInterfaces() const
02762 {
02763 if(!interfaces.empty())
02764 {
02765
02766 for(unsigned int i=0;i<interfaces.size();i++)
02767 {
02768 ASObject* target;
02769 ASObject* interface_obj=getGlobal()->getVariableAndTargetByMultiname(interfaces[i], target);
02770 assert_and_throw(interface_obj && interface_obj->getObjectType()==T_CLASS);
02771 Class_base* inter=static_cast<Class_base*>(interface_obj);
02772
02773 interfaces_added.push_back(inter);
02774
02775 inter->getInterfaces();
02776 }
02777
02778 interfaces.clear();
02779 }
02780 return interfaces_added;
02781 }
02782
02783 void Class_base::linkInterface(Class_base* c) const
02784 {
02785 if(class_index==-1)
02786 {
02787
02788 return;
02789 }
02790
02791 for(unsigned int i=0;i<getInterfaces().size();i++)
02792 getInterfaces()[i]->linkInterface(c);
02793
02794 assert_and_throw(context);
02795
02796
02797 for(unsigned int j=0;j<context->instances[class_index].trait_count;j++)
02798 {
02799 traits_info* t=&context->instances[class_index].traits[j];
02800 context->linkTrait(c,t);
02801 }
02802
02803 if(constructor)
02804 {
02805 LOG(LOG_CALLS,_("Calling interface init for ") << class_name);
02806 ASObject* ret=constructor->call(c,NULL,0);
02807 assert_and_throw(ret==NULL);
02808 }
02809 }
02810
02811 bool Class_base::isSubClass(const Class_base* cls) const
02812 {
02813 check();
02814 if(cls==this)
02815 return true;
02816
02817
02818 for(unsigned int i=0;i<getInterfaces().size();i++)
02819 {
02820 if(getInterfaces()[i]->isSubClass(cls))
02821 return true;
02822 }
02823
02824
02825 if(super && super->isSubClass(cls))
02826 return true;
02827 return false;
02828 }
02829
02830 tiny_string Class_base::getQualifiedClassName() const
02831 {
02832
02833 if(class_index==-1)
02834 return class_name.name;
02835 else
02836 {
02837 assert_and_throw(context);
02838 int name_index=context->instances[class_index].name;
02839 assert_and_throw(name_index);
02840 const multiname* mname=context->getMultiname(name_index,NULL);
02841 return mname->qualifiedString();
02842 }
02843 }
02844
02845 void ASQName::sinit(Class_base* c)
02846 {
02847 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02848 }
02849
02850 ASFUNCTIONBODY(ASQName,_constructor)
02851 {
02852 ASQName* th=static_cast<ASQName*>(obj);
02853 if(argslen!=2)
02854 throw UnsupportedException("ArgumentError");
02855
02856 assert_and_throw(args[0]->getObjectType()==T_STRING || args[0]->getObjectType()==T_NAMESPACE);
02857 assert_and_throw(args[1]->getObjectType()==T_STRING);
02858
02859 switch(args[0]->getObjectType())
02860 {
02861 case T_STRING:
02862 {
02863 ASString* s=static_cast<ASString*>(args[0]);
02864 th->uri=s->data;
02865 break;
02866 }
02867 case T_NAMESPACE:
02868 {
02869 Namespace* n=static_cast<Namespace*>(args[0]);
02870 th->uri=n->uri;
02871 break;
02872 }
02873 default:
02874 throw UnsupportedException("QName not completely implemented");
02875 }
02876 th->local_name=args[1]->toString();
02877 return NULL;
02878 }
02879
02880 void Namespace::sinit(Class_base* c)
02881 {
02882 c->setConstructor(Class<IFunction>::getFunction(_constructor));
02883 }
02884
02885 void Namespace::buildTraits(ASObject* o)
02886 {
02887 }
02888
02889 ASFUNCTIONBODY(Namespace,_constructor)
02890 {
02891 assert_and_throw(argslen==0);
02892 return NULL;
02893 }
02894
02895 void InterfaceClass::lookupAndLink(ASObject* o, const tiny_string& name, const tiny_string& interfaceNs)
02896 {
02897 ASObject* ret=o->getVariableByQName(name,"");
02898 assert_and_throw(ret);
02899 ret->incRef();
02900 o->setVariableByQName(name,interfaceNs,ret);
02901 }
02902
02903 void UInteger::sinit(Class_base* c)
02904 {
02905
02906
02907 c->setVariableByQName("MAX_VALUE","",new UInteger(0x7fffffff));
02908 c->super=Class<ASObject>::getClass();
02909 c->max_level=c->super->max_level+1;
02910 }
02911
02912 bool UInteger::isEqual(ASObject* o)
02913 {
02914 if(o->getObjectType()==T_INTEGER)
02915 {
02916
02917 return val==o->toUInt();
02918 }
02919 else if(o->getObjectType()==T_UINTEGER)
02920 return val==o->toUInt();
02921 else if(o->getObjectType()==T_NUMBER)
02922 return val==o->toUInt();
02923 else
02924 {
02925 return ASObject::isEqual(o);
02926 }
02927 }
02928
02929 Class<IFunction>* Class<IFunction>::getClass()
02930 {
02931 std::map<QName, Class_base*>::iterator it=sys->classes.find(QName(ClassName<IFunction>::name,ClassName<IFunction>::ns));
02932 Class<IFunction>* ret=NULL;
02933 if(it==sys->classes.end())
02934 {
02935 ret=new Class<IFunction>;
02936 sys->classes.insert(std::make_pair(QName(ClassName<IFunction>::name,ClassName<IFunction>::ns),ret));
02937 IFunction::sinit(ret);
02938 }
02939 else
02940 ret=static_cast<Class<IFunction>*>(it->second);
02941
02942 ret->incRef();
02943 return ret;
02944 }
02945
02946 void GlobalObject::registerGlobalScope(ASObject* scope)
02947 {
02948 globalScopes.push_back(scope);
02949 }
02950
02951 ASObject* GlobalObject::getVariableByString(const std::string& str, ASObject*& target)
02952 {
02953 size_t index=str.rfind('.');
02954 multiname name;
02955 name.name_type=multiname::NAME_STRING;
02956 if(index==str.npos)
02957 {
02958 name.name_s=str;
02959 name.ns.push_back(nsNameAndKind("",0));
02960 }
02961 else
02962 {
02963 name.name_s=str.substr(index+1);
02964 name.ns.push_back(nsNameAndKind(str.substr(0,index),0));
02965 }
02966 return getVariableAndTargetByMultiname(name, target);
02967 }
02968
02969 ASObject* GlobalObject::getVariableAndTargetByMultiname(const multiname& name, ASObject*& target)
02970 {
02971 ASObject* o=NULL;
02972 for(uint32_t i=0;i<globalScopes.size();i++)
02973 {
02974 o=globalScopes[i]->getVariableByMultiname(name);
02975 if(o)
02976 {
02977 target=globalScopes[i];
02978 break;
02979 }
02980 }
02981 return o;
02982 }
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000 bool lightspark::Boolean_concrete(ASObject* obj)
03001 {
03002 if(obj->getObjectType()==T_STRING)
03003 {
03004 LOG(LOG_CALLS,_("String to bool"));
03005 const tiny_string& s=obj->toString();
03006 if(s.len()==0)
03007 return false;
03008 else
03009 return true;
03010 }
03011 else if(obj->getObjectType()==T_BOOLEAN)
03012 {
03013 Boolean* b=static_cast<Boolean*>(obj);
03014 LOG(LOG_CALLS,_("Boolean to bool ") << b->val);
03015 return b->val;
03016 }
03017 else if(obj->getObjectType()==T_OBJECT)
03018 {
03019 LOG(LOG_CALLS,_("Object to bool"));
03020 return true;
03021 }
03022 else if(obj->getObjectType()==T_CLASS)
03023 {
03024 LOG(LOG_CALLS,_("Class to bool"));
03025 return true;
03026 }
03027 else if(obj->getObjectType()==T_ARRAY)
03028 {
03029 LOG(LOG_CALLS,_("Array to bool"));
03030 return true;
03031 }
03032 else if(obj->getObjectType()==T_UNDEFINED)
03033 {
03034 LOG(LOG_CALLS,_("Undefined to bool"));
03035 return false;
03036 }
03037 else if(obj->getObjectType()==T_NULL)
03038 {
03039 LOG(LOG_CALLS,_("Null to bool"));
03040 return false;
03041 }
03042 else if(obj->getObjectType()==T_NUMBER)
03043 {
03044 LOG(LOG_CALLS,_("Number to bool"));
03045 double val=obj->toNumber();
03046 if(val==0 || isnan(val))
03047 return false;
03048 else
03049 return true;
03050 }
03051 else if(obj->getObjectType()==T_INTEGER)
03052 {
03053 LOG(LOG_CALLS,_("Integer to bool"));
03054 int32_t val=obj->toInt();
03055 if(val==0)
03056 return false;
03057 else
03058 return true;
03059 }
03060 else
03061 {
03062 LOG(LOG_NOT_IMPLEMENTED,_("Boolean conversion for type ") << obj->getObjectType() << endl);
03063 return false;
03064 }
03065 }
03066
03067 ASFUNCTIONBODY(lightspark,parseInt)
03068 {
03069 if(args[0]->getObjectType()==T_UNDEFINED)
03070 return new Undefined;
03071 else
03072 {
03073 const tiny_string& val=args[0]->toString();
03074 const char* cur=val.raw_buf();
03075 int ret=0;
03076 if(strncmp(cur,"0x",2)==0)
03077 {
03078 cur+=2;
03079 while(*cur)
03080 {
03081 ret<<=4;
03082 ret+=Math::hexToInt(*cur);
03083 cur++;
03084 }
03085 }
03086 else
03087 ret=atoi(cur);
03088 return abstract_i(ret);
03089 }
03090 }
03091
03092 ASFUNCTIONBODY(lightspark,parseFloat)
03093 {
03094 if(args[0]->getObjectType()==T_UNDEFINED)
03095 return new Undefined;
03096 else
03097 return abstract_d(atof(args[0]->toString().raw_buf()));
03098 }
03099
03100 ASFUNCTIONBODY(lightspark,isNaN)
03101 {
03102 if(args[0]->getObjectType()==T_UNDEFINED)
03103 return abstract_b(true);
03104 else if(args[0]->getObjectType()==T_INTEGER)
03105 return abstract_b(false);
03106 else if(args[0]->getObjectType()==T_NUMBER)
03107 {
03108 if(isnan(args[0]->toNumber()))
03109 return abstract_b(true);
03110 else
03111 return abstract_b(false);
03112 }
03113 else if(args[0]->getObjectType()==T_BOOLEAN)
03114 return abstract_b(false);
03115 else if(args[0]->getObjectType()==T_STRING)
03116 {
03117 double n=args[0]->toNumber();
03118 return abstract_b(isnan(n));
03119 }
03120 else
03121 throw UnsupportedException("Weird argument for isNaN");
03122 }
03123
03124 ASFUNCTIONBODY(lightspark,isFinite)
03125 {
03126 if(args[0]->getObjectType()==T_NUMBER)
03127 {
03128 if(isfinite(args[0]->toNumber()))
03129 return abstract_b(true);
03130 else
03131 return abstract_b(false);
03132 }
03133 else
03134 throw UnsupportedException("Weird argument for isNaN");
03135 }
03136
03137 ASFUNCTIONBODY(lightspark,unescape)
03138 {
03139 ASString* th=static_cast<ASString*>(args[0]);
03140 string ret;
03141 ret.reserve(th->data.size());
03142 for(unsigned int i=0;i<th->data.size();i++)
03143 {
03144 if(th->data[i]=='%')
03145 throw UnsupportedException("Unescape not completely implemented");
03146 else
03147 ret.push_back(th->data[i]);
03148 }
03149 return Class<ASString>::getInstanceS(ret);
03150 }
03151
03152 ASFUNCTIONBODY(lightspark,print)
03153 {
03154 if(args[0]->getObjectType() == T_STRING)
03155 {
03156 ASString* str = static_cast<ASString*>(args[0]);
03157 cerr << str->data << endl;
03158 }
03159 else
03160 cerr << args[0]->toString() << endl;
03161 return NULL;
03162 }
03163
03164 ASFUNCTIONBODY(lightspark,trace)
03165 {
03166 for(intptr_t i = 0; i< argslen;i++)
03167 {
03168 if(i > 0)
03169 cerr << " ";
03170
03171 if(args[i]->getObjectType() == T_STRING)
03172 {
03173 ASString* str = static_cast<ASString*>(args[i]);
03174 cerr << str->data;
03175 }
03176 else
03177 cerr << args[i]->toString();
03178 }
03179 cerr << endl;
03180 return NULL;
03181 }