# sqbaselib.cpp

    00001 /*
    00002   see copyright notice in squirrel.h
    00003 */
    00004 #include "sqpcheader.h"
    00005 #include "sqvm.h"
    00006 #include "sqstring.h"
    00007 #include "sqtable.h"
    00008 #include "sqarray.h"
    00009 #include "sqfuncproto.h"
    00010 #include "sqclosure.h"
    00011 #include "sqclass.h"
    00012 #include <stdlib.h>
    00013 #include <stdarg.h>
    00014 #include <ctype.h>
    00015
    00016 bool str2num(const SQChar *s,SQObjectPtr &res)
    00017 {
    00018   SQChar *end;
    00019   if(scstrstr(s,_SC("."))){
    00020     SQFloat r = SQFloat(scstrtod(s,&end));
    00021     if(s == end) return false;
    00022     res = r;
    00023     return true;
    00024   }
    00025   else{
    00026     SQInteger r = SQInteger(scstrtol(s,&end,10));
    00027     if(s == end) return false;
    00028     res = r;
    00029     return true;
    00030   }
    00031 }
    00032
    00033 #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
    00034 static SQInteger base_dummy(HSQUIRRELVM v)
    00035 {
    00036   return 0;
    00037 }
    00038
    00039 #ifndef NO_GARBAGE_COLLECTOR
    00040 static SQInteger base_collectgarbage(HSQUIRRELVM v)
    00041 {
    00042   sq_pushinteger(v, sq_collectgarbage(v));
    00043   return 1;
    00044 }
    00045 #endif
    00046
    00047 static SQInteger base_getroottable(HSQUIRRELVM v)
    00048 {
    00049   v->Push(v->_roottable);
    00050   return 1;
    00051 }
    00052
    00053 static SQInteger base_getconsttable(HSQUIRRELVM v)
    00054 {
    00055   v->Push(_ss(v)->_consts);
    00056   return 1;
    00057 }
    00058
    00059
    00060 static SQInteger base_setroottable(HSQUIRRELVM v)
    00061 {
    00062   SQObjectPtr &o=stack_get(v,2);
    00063   if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
    00064   v->Push(o);
    00065   return 1;
    00066 }
    00067
    00068 static SQInteger base_setconsttable(HSQUIRRELVM v)
    00069 {
    00070   SQObjectPtr &o=stack_get(v,2);
    00071   if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
    00072   v->Push(o);
    00073   return 1;
    00074 }
    00075
    00076 static SQInteger base_seterrorhandler(HSQUIRRELVM v)
    00077 {
    00078   sq_seterrorhandler(v);
    00079   return 0;
    00080 }
    00081
    00082 static SQInteger base_setdebughook(HSQUIRRELVM v)
    00083 {
    00084   sq_setdebughook(v);
    00085   return 0;
    00086 }
    00087
    00088 static SQInteger base_enabledebuginfo(HSQUIRRELVM v)
    00089 {
    00090   SQObjectPtr &o=stack_get(v,2);
    00091   sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);
    00092   return 0;
    00093 }
    00094
    00095 static SQInteger base_getstackinfos(HSQUIRRELVM v)
    00096 {
    00097   SQInteger level;
    00098   SQStackInfos si;
    00099   SQInteger seq = 0;
    00100   const SQChar *name = NULL;
    00101   sq_getinteger(v, -1, &level);
    00102   if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
    00103   {
    00104     const SQChar *fn = _SC("unknown");
    00105     const SQChar *src = _SC("unknown");
    00106     if(si.funcname)fn = si.funcname;
    00107     if(si.source)src = si.source;
    00108     sq_newtable(v);
    00109     sq_pushstring(v, _SC("func"), -1);
    00110     sq_pushstring(v, fn, -1);
    00111     sq_createslot(v, -3);
    00112     sq_pushstring(v, _SC("src"), -1);
    00113     sq_pushstring(v, src, -1);
    00114     sq_createslot(v, -3);
    00115     sq_pushstring(v, _SC("line"), -1);
    00116     sq_pushinteger(v, si.line);
    00117     sq_createslot(v, -3);
    00118     sq_pushstring(v, _SC("locals"), -1);
    00119     sq_newtable(v);
    00120     seq=0;
    00121     while ((name = sq_getlocal(v, level, seq))) {
    00122       sq_pushstring(v, name, -1);
    00123       sq_push(v, -2);
    00124       sq_createslot(v, -4);
    00125       sq_pop(v, 1);
    00126       seq++;
    00127     }
    00128     sq_createslot(v, -3);
    00129     return 1;
    00130   }
    00131
    00132   return 0;
    00133 }
    00134 #endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */
    00135
    00136 static SQInteger base_assert(HSQUIRRELVM v)
    00137 {
    00138   if(v->IsFalse(stack_get(v,2))){
    00139     return sq_throwerror(v,_SC("assertion failed"));
    00140   }
    00141   return 0;
    00142 }
    00143
    00144 static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)
    00145 {
    00146   SQInteger top = sq_gettop(v);
    00147   sidx=0;
    00148   eidx=0;
    00149   o=stack_get(v,1);
    00150   SQObjectPtr &start=stack_get(v,2);
    00151   if(type(start)!=OT_NULL && sq_isnumeric(start)){
    00152     sidx=tointeger(start);
    00153   }
    00154   if(top>2){
    00155     SQObjectPtr &end=stack_get(v,3);
    00156     if(sq_isnumeric(end)){
    00157       eidx=tointeger(end);
    00158     }
    00159   }
    00160   else {
    00161     eidx = sq_getsize(v,1);
    00162   }
    00163   return 1;
    00164 }
    00165
    00166 static SQInteger base_print(HSQUIRRELVM v)
    00167 {
    00168   const SQChar *str;
    00169   sq_tostring(v,2);
    00170   sq_getstring(v,-1,&str);
    00171   if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
    00172   return 0;
    00173 }
    00174
    00175 #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
    00176 static SQInteger base_compilestring(HSQUIRRELVM v)
    00177 {
    00178   SQInteger nargs=sq_gettop(v);
    00179   const SQChar *src=NULL,*name=_SC("unnamedbuffer");
    00180   SQInteger size;
    00181   sq_getstring(v,2,&src);
    00182   size=sq_getsize(v,2);
    00183   if(nargs>2){
    00184     sq_getstring(v,3,&name);
    00185   }
    00186   if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
    00187     return 1;
    00188   else
    00189     return SQ_ERROR;
    00190 }
    00191
    00192 static SQInteger base_newthread(HSQUIRRELVM v)
    00193 {
    00194   SQObjectPtr &func = stack_get(v,2);
    00195   SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;
    00196   HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
    00197   sq_move(newv,v,-2);
    00198   return 1;
    00199 }
    00200
    00201 static SQInteger base_suspend(HSQUIRRELVM v)
    00202 {
    00203   return sq_suspendvm(v);
    00204 }
    00205 #endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */
    00206
    00207 static SQInteger base_array(HSQUIRRELVM v)
    00208 {
    00209   SQArray *a;
    00210   SQObject &size = stack_get(v,2);
    00211   if(sq_gettop(v) > 2) {
    00212     a = SQArray::Create(_ss(v),0);
    00213     a->Resize(tointeger(size),stack_get(v,3));
    00214   }
    00215   else {
    00216     a = SQArray::Create(_ss(v),tointeger(size));
    00217   }
    00218   v->Push(a);
    00219   return 1;
    00220 }
    00221
    00222 static SQInteger base_type(HSQUIRRELVM v)
    00223 {
    00224   SQObjectPtr &o = stack_get(v,2);
    00225   v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
    00226   return 1;
    00227 }
    00228
    00229 static SQRegFunction base_funcs[]={
    00230   //generic
    00231 #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
    00232   {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
    00233   {_SC("setdebughook"),base_setdebughook,2, NULL},
    00234   {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
    00235   {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
    00236   {_SC("getroottable"),base_getroottable,1, NULL},
    00237   {_SC("setroottable"),base_setroottable,2, NULL},
    00238   {_SC("getconsttable"),base_getconsttable,1, NULL},
    00239   {_SC("setconsttable"),base_setconsttable,2, NULL},
    00240 #endif
    00241   {_SC("assert"),base_assert,2, NULL},
    00242   {_SC("print"),base_print,2, NULL},
    00243 #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
    00244   {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
    00245   {_SC("newthread"),base_newthread,2, _SC(".c")},
    00246   {_SC("suspend"),base_suspend,-1, NULL},
    00247 #endif
    00248   {_SC("array"),base_array,-2, _SC(".n")},
    00249   {_SC("type"),base_type,2, NULL},
    00250 #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS
    00251   {_SC("dummy"),base_dummy,0,NULL},
    00252 #ifndef NO_GARBAGE_COLLECTOR
    00253   {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
    00254 #endif
    00255 #endif
    00256   {0,0,0,0}
    00257 };
    00258
    00259 void sq_base_register(HSQUIRRELVM v)
    00260 {
    00261   SQInteger i=0;
    00262   sq_pushroottable(v);
    00263   while(base_funcs[i].name!=0) {
    00264     sq_pushstring(v,base_funcs[i].name,-1);
    00265     sq_newclosure(v,base_funcs[i].f,0);
    00266     sq_setnativeclosurename(v,-1,base_funcs[i].name);
    00267     sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
    00268     sq_createslot(v,-3);
    00269     i++;
    00270   }
    00271   sq_pushstring(v,_SC("_version_"),-1);
    00272   sq_pushstring(v,SQUIRREL_VERSION,-1);
    00273   sq_createslot(v,-3);
    00274   sq_pushstring(v,_SC("_charsize_"),-1);
    00275   sq_pushinteger(v,sizeof(SQChar));
    00276   sq_createslot(v,-3);
    00277   sq_pushstring(v,_SC("_intsize_"),-1);
    00278   sq_pushinteger(v,sizeof(SQInteger));
    00279   sq_createslot(v,-3);
    00280   sq_pop(v,1);
    00281 }
    00282
    00283 static SQInteger default_delegate_len(HSQUIRRELVM v)
    00284 {
    00285   v->Push(SQInteger(sq_getsize(v,1)));
    00286   return 1;
    00287 }
    00288
    00289 static SQInteger default_delegate_tofloat(HSQUIRRELVM v)
    00290 {
    00291   SQObjectPtr &o=stack_get(v,1);
    00292   switch(type(o)){
    00293   case OT_STRING:{
    00294     SQObjectPtr res;
    00295     if(str2num(_stringval(o),res)){
    00296       v->Push(SQObjectPtr(tofloat(res)));
    00297       break;
    00298     }}
    00299     return sq_throwerror(v, _SC("cannot convert the string"));
    00300     break;
    00301   case OT_INTEGER:case OT_FLOAT:
    00302     v->Push(SQObjectPtr(tofloat(o)));
    00303     break;
    00304   case OT_BOOL:
    00305     v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
    00306     break;
    00307   default:
    00308     v->Push(_null_);
    00309     break;
    00310   }
    00311   return 1;
    00312 }
    00313
    00314 static SQInteger default_delegate_tointeger(HSQUIRRELVM v)
    00315 {
    00316   SQObjectPtr &o=stack_get(v,1);
    00317   switch(type(o)){
    00318   case OT_STRING:{
    00319     SQObjectPtr res;
    00320     if(str2num(_stringval(o),res)){
    00321       v->Push(SQObjectPtr(tointeger(res)));
    00322       break;
    00323     }}
    00324     return sq_throwerror(v, _SC("cannot convert the string"));
    00325     break;
    00326   case OT_INTEGER:case OT_FLOAT:
    00327     v->Push(SQObjectPtr(tointeger(o)));
    00328     break;
    00329   case OT_BOOL:
    00330     v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));
    00331     break;
    00332   default:
    00333     v->Push(_null_);
    00334     break;
    00335   }
    00336   return 1;
    00337 }
    00338
    00339 static SQInteger default_delegate_tostring(HSQUIRRELVM v)
    00340 {
    00341   sq_tostring(v,1);
    00342   return 1;
    00343 }
    00344
    00345 static SQInteger obj_delegate_weakref(HSQUIRRELVM v)
    00346 {
    00347   sq_weakref(v,1);
    00348   return 1;
    00349 }
    00350
    00351 static SQInteger obj_clear(HSQUIRRELVM v)
    00352 {
    00353   return sq_clear(v,-1);
    00354 }
    00355
    00356
    00357 static SQInteger number_delegate_tochar(HSQUIRRELVM v)
    00358 {
    00359   SQObject &o=stack_get(v,1);
    00360   SQChar c = (SQChar)tointeger(o);
    00361   v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
    00362   return 1;
    00363 }
    00364
    00365
    00367 //TABLE DEFAULT DELEGATE
    00368
    00369 static SQInteger table_rawdelete(HSQUIRRELVM v)
    00370 {
    00371   if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
    00372     return SQ_ERROR;
    00373   return 1;
    00374 }
    00375
    00376
    00377 static SQInteger container_rawexists(HSQUIRRELVM v)
    00378 {
    00379   if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
    00380     sq_pushbool(v,SQTrue);
    00381     return 1;
    00382   }
    00383   sq_pushbool(v,SQFalse);
    00384   return 1;
    00385 }
    00386
    00387 static SQInteger table_rawset(HSQUIRRELVM v)
    00388 {
    00389   return sq_rawset(v,-3);
    00390 }
    00391
    00392
    00393 static SQInteger table_rawget(HSQUIRRELVM v)
    00394 {
    00395   return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
    00396 }
    00397
    00398
    00399 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
    00400   {_SC("len"),default_delegate_len,1, _SC("t")},
    00401   {_SC("rawget"),table_rawget,2, _SC("t")},
    00402   {_SC("rawset"),table_rawset,3, _SC("t")},
    00403   {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
    00404   {_SC("rawin"),container_rawexists,2, _SC("t")},
    00405   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00406   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00407   {_SC("clear"),obj_clear,1, _SC(".")},
    00408   {0,0,0,0}
    00409 };
    00410
    00411 //ARRAY DEFAULT DELEGATE///////////////////////////////////////
    00412
    00413 static SQInteger array_append(HSQUIRRELVM v)
    00414 {
    00415   return sq_arrayappend(v,-2);
    00416 }
    00417
    00418 static SQInteger array_extend(HSQUIRRELVM v)
    00419 {
    00420   _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
    00421   return 0;
    00422 }
    00423
    00424 static SQInteger array_reverse(HSQUIRRELVM v)
    00425 {
    00426   return sq_arrayreverse(v,-1);
    00427 }
    00428
    00429 static SQInteger array_pop(HSQUIRRELVM v)
    00430 {
    00431   return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
    00432 }
    00433
    00434 static SQInteger array_top(HSQUIRRELVM v)
    00435 {
    00436   SQObject &o=stack_get(v,1);
    00437   if(_array(o)->Size()>0){
    00438     v->Push(_array(o)->Top());
    00439     return 1;
    00440   }
    00441   else return sq_throwerror(v,_SC("top() on a empty array"));
    00442 }
    00443
    00444 static SQInteger array_insert(HSQUIRRELVM v)
    00445 {
    00446   SQObject &o=stack_get(v,1);
    00447   SQObject &idx=stack_get(v,2);
    00448   SQObject &val=stack_get(v,3);
    00449   if(!_array(o)->Insert(tointeger(idx),val))
    00450     return sq_throwerror(v,_SC("index out of range"));
    00451   return 0;
    00452 }
    00453
    00454 static SQInteger array_remove(HSQUIRRELVM v)
    00455 {
    00456   SQObject &o = stack_get(v, 1);
    00457   SQObject &idx = stack_get(v, 2);
    00458   if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
    00459   SQObjectPtr val;
    00460   if(_array(o)->Get(tointeger(idx), val)) {
    00461     _array(o)->Remove(tointeger(idx));
    00462     v->Push(val);
    00463     return 1;
    00464   }
    00465   return sq_throwerror(v, _SC("idx out of range"));
    00466 }
    00467
    00468 static SQInteger array_resize(HSQUIRRELVM v)
    00469 {
    00470   SQObject &o = stack_get(v, 1);
    00471   SQObject &nsize = stack_get(v, 2);
    00472   SQObjectPtr fill;
    00473   if(sq_isnumeric(nsize)) {
    00474     if(sq_gettop(v) > 2)
    00475       fill = stack_get(v, 3);
    00476     _array(o)->Resize(tointeger(nsize),fill);
    00477     return 0;
    00478   }
    00479   return sq_throwerror(v, _SC("size must be a number"));
    00480 }
    00481
    00482
    00483 //QSORT ala Sedgewick
    00484 bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)
    00485 {
    00486   if(func < 0) {
    00487     if(!v->ObjCmp(a,b,ret)) return false;
    00488   }
    00489   else {
    00490     SQInteger top = sq_gettop(v);
    00491     sq_push(v, func);
    00492     sq_pushroottable(v);
    00493     v->Push(a);
    00494     v->Push(b);
    00495     if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) {
    00496       if(!sq_isstring( v->_lasterror))
    00497         v->Raise_Error(_SC("compare func failed"));
    00498       return false;
    00499     }
    00500     sq_getinteger(v, -1, &ret);
    00501     sq_settop(v, top);
    00502     return true;
    00503   }
    00504   return true;
    00505 }
    00506 //QSORT ala Sedgewick
    00507 bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)
    00508 {
    00509   SQInteger i, j;
    00510   SQArray *a=_array(arr);
    00511   SQObjectPtr pivot,t;
    00512   if( l < r ){
    00513     pivot = a->_values[l];
    00514     i = l; j = r+1;
    00515     while(1){
    00516       SQInteger ret;
    00517       do {
    00518         ++i;
    00519         if(i > r) break;
    00520         if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))
    00521           return false;
    00522       } while( ret <= 0);
    00523       do {
    00524         --j;
    00525         if ( j < 0 ) {
    00526           v->Raise_Error( _SC("Invalid qsort, probably compare function defect") );
    00527           return false;
    00528         }
    00529         if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))
    00530           return false;
    00531       }
    00532       while( ret > 0 );
    00533       if( i >= j ) break;
    00534       t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;
    00535     }
    00536     t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;
    00537     if(!_qsort( v, arr, l, j-1,func)) return false;
    00538     if(!_qsort( v, arr, j+1, r,func)) return false;
    00539   }
    00540   return true;
    00541 }
    00542
    00543 static SQInteger array_sort(HSQUIRRELVM v)
    00544 {
    00545   SQInteger func = -1;
    00546   SQObjectPtr &o = stack_get(v,1);
    00547   SQObject &funcobj = stack_get(v,2);
    00548   if(_array(o)->Size() > 1) {
    00549     if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;
    00550     if(!_qsort(v, o, 0, _array(o)->Size()-1, func))
    00551       return SQ_ERROR;
    00552
    00553   }
    00554   return 0;
    00555 }
    00556 static SQInteger array_slice(HSQUIRRELVM v)
    00557 {
    00558   SQInteger sidx,eidx;
    00559   SQObjectPtr o;
    00560   if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
    00561   SQInteger alen = _array(o)->Size();
    00562   if(sidx < 0)sidx = alen + sidx;
    00563   if(eidx < 0)eidx = alen + eidx;
    00564   if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));
    00565   if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));
    00566   SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
    00567   SQObjectPtr t;
    00568   SQInteger count=0;
    00569   for(SQInteger i=sidx;i<eidx;i++){
    00570     _array(o)->Get(i,t);
    00571     arr->Set(count++,t);
    00572   }
    00573   v->Push(arr);
    00574   return 1;
    00575
    00576 }
    00577
    00578 SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
    00579   {_SC("len"),default_delegate_len,1, _SC("a")},
    00580   {_SC("append"),array_append,2, _SC("a")},
    00581   {_SC("extend"),array_extend,2, _SC("aa")},
    00582   {_SC("push"),array_append,2, _SC("a")},
    00583   {_SC("pop"),array_pop,1, _SC("a")},
    00584   {_SC("top"),array_top,1, _SC("a")},
    00585   {_SC("insert"),array_insert,3, _SC("an")},
    00586   {_SC("remove"),array_remove,2, _SC("an")},
    00587   {_SC("resize"),array_resize,-2, _SC("an")},
    00588   {_SC("reverse"),array_reverse,1, _SC("a")},
    00589   {_SC("sort"),array_sort,-1, _SC("ac")},
    00590   {_SC("slice"),array_slice,-1, _SC("ann")},
    00591   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00592   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00593   {_SC("clear"),obj_clear,1, _SC(".")},
    00594   {0,0,0,0}
    00595 };
    00596
    00597 //STRING DEFAULT DELEGATE//////////////////////////
    00598 static SQInteger string_slice(HSQUIRRELVM v)
    00599 {
    00600   SQInteger sidx,eidx;
    00601   SQObjectPtr o;
    00602   if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
    00603   SQInteger slen = _string(o)->_len;
    00604   if(sidx < 0)sidx = slen + sidx;
    00605   if(eidx < 0)eidx = slen + eidx;
    00606   if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));
    00607   if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));
    00608   v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
    00609   return 1;
    00610 }
    00611
    00612 static SQInteger string_find(HSQUIRRELVM v)
    00613 {
    00614   SQInteger top,start_idx=0;
    00615   const SQChar *str,*substr,*ret;
    00616   if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){
    00617     if(top>2)sq_getinteger(v,3,&start_idx);
    00618     if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){
    00619       ret=scstrstr(&str[start_idx],substr);
    00620       if(ret){
    00621         sq_pushinteger(v,(SQInteger)(ret-str));
    00622         return 1;
    00623       }
    00624     }
    00625     return 0;
    00626   }
    00627   return sq_throwerror(v,_SC("invalid param"));
    00628 }
    00629
    00630 #define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \
    00631 { \
    00632   SQObject str=stack_get(v,1); \
    00633   SQInteger len=_string(str)->_len; \
    00634   const SQChar *sThis=_stringval(str); \
    00635   SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
    00636   for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \
    00637   v->Push(SQString::Create(_ss(v),sNew,len)); \
    00638   return 1; \
    00639 }
    00640
    00641
    00642 STRING_TOFUNCZ(tolower)
    00643 STRING_TOFUNCZ(toupper)
    00644
    00645 SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
    00646   {_SC("len"),default_delegate_len,1, _SC("s")},
    00647   {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},
    00648   {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},
    00649   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00650   {_SC("slice"),string_slice,-1, _SC(" s n  n")},
    00651   {_SC("find"),string_find,-2, _SC("s s n ")},
    00652   {_SC("tolower"),string_tolower,1, _SC("s")},
    00653   {_SC("toupper"),string_toupper,1, _SC("s")},
    00654   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00655   {0,0,0,0}
    00656 };
    00657
    00658 //INTEGER DEFAULT DELEGATE//////////////////////////
    00659 SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
    00660   {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
    00661   {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
    00662   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00663   {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
    00664   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00665   {0,0,0,0}
    00666 };
    00667
    00668 //CLOSURE DEFAULT DELEGATE//////////////////////////
    00669 static SQInteger closure_pcall(HSQUIRRELVM v)
    00670 {
    00671   return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;
    00672 }
    00673
    00674 static SQInteger closure_call(HSQUIRRELVM v)
    00675 {
    00676   return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
    00677 }
    00678
    00679 static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)
    00680 {
    00681   SQArray *aparams=_array(stack_get(v,2));
    00682   SQInteger nparams=aparams->Size();
    00683   v->Push(stack_get(v,1));
    00684   for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
    00685   return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;
    00686 }
    00687
    00688 static SQInteger closure_acall(HSQUIRRELVM v)
    00689 {
    00690   return _closure_acall(v,SQTrue);
    00691 }
    00692
    00693 static SQInteger closure_pacall(HSQUIRRELVM v)
    00694 {
    00695   return _closure_acall(v,SQFalse);
    00696 }
    00697
    00698 static SQInteger closure_bindenv(HSQUIRRELVM v)
    00699 {
    00700   if(SQ_FAILED(sq_bindenv(v,1)))
    00701     return SQ_ERROR;
    00702   return 1;
    00703 }
    00704
    00705 static SQInteger closure_getinfos(HSQUIRRELVM v) {
    00706   SQObject o = stack_get(v,1);
    00707   SQTable *res = SQTable::Create(_ss(v),4);
    00708   if(type(o) == OT_CLOSURE) {
    00709     SQFunctionProto *f = _funcproto(_closure(o)->_function);
    00710     SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
    00711     SQObjectPtr params = SQArray::Create(_ss(v),nparams);
    00712     for(SQInteger n = 0; n<f->_nparameters; n++) {
    00713       _array(params)->Set((SQInteger)n,f->_parameters[n]);
    00714     }
    00715     if(f->_varparams) {
    00716       _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));
    00717     }
    00718     res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false);
    00719     res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name);
    00720     res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);
    00721     res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);
    00722     res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);
    00723   }
    00724   else { //OT_NATIVECLOSURE
    00725     SQNativeClosure *nc = _nativeclosure(o);
    00726     res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);
    00727     res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);
    00728     res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
    00729     SQObjectPtr typecheck;
    00730     if(nc->_typecheck.size() > 0) {
    00731       typecheck =
    00732         SQArray::Create(_ss(v), nc->_typecheck.size());
    00733       for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
    00734           _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
    00735       }
    00736     }
    00737     res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
    00738   }
    00739   v->Push(res);
    00740   return 1;
    00741 }
    00742
    00743
    00744 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
    00745   {_SC("call"),closure_call,-1, _SC("c")},
    00746   {_SC("pcall"),closure_pcall,-1, _SC("c")},
    00747   {_SC("acall"),closure_acall,2, _SC("ca")},
    00748   {_SC("pacall"),closure_pacall,2, _SC("ca")},
    00749   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00750   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00751   {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
    00752   {_SC("getinfos"),closure_getinfos,1, _SC("c")},
    00753   {0,0,0,0}
    00754 };
    00755
    00756 //GENERATOR DEFAULT DELEGATE
    00757 static SQInteger generator_getstatus(HSQUIRRELVM v)
    00758 {
    00759   SQObject &o=stack_get(v,1);
    00760   switch(_generator(o)->_state){
    00761     case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;
    00762     case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;
    00763     case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;
    00764   }
    00765   return 1;
    00766 }
    00767
    00768 SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
    00769   {_SC("getstatus"),generator_getstatus,1, _SC("g")},
    00770   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00771   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00772   {0,0,0,0}
    00773 };
    00774
    00775 //THREAD DEFAULT DELEGATE
    00776
    00777 static SQInteger thread_call(HSQUIRRELVM v)
    00778 {
    00779
    00780   SQObjectPtr o = stack_get(v,1);
    00781   if(type(o) == OT_THREAD) {
    00782     SQInteger nparams = sq_gettop(v);
    00783     _thread(o)->Push(_thread(o)->_roottable);
    00784     for(SQInteger i = 2; i<(nparams+1); i++)
    00785       sq_move(_thread(o),v,i);
    00786     if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) {
    00787       sq_move(v,_thread(o),-1);
    00788       sq_pop(_thread(o),1);
    00789       return 1;
    00790     }
    00791     v->_lasterror = _thread(o)->_lasterror;
    00792     return SQ_ERROR;
    00793   }
    00794   return sq_throwerror(v,_SC("wrong parameter"));
    00795 }
    00796
    00797 static SQInteger thread_wakeup(HSQUIRRELVM v)
    00798 {
    00799   SQObjectPtr o = stack_get(v,1);
    00800   if(type(o) == OT_THREAD) {
    00801     SQVM *thread = _thread(o);
    00802     SQInteger state = sq_getvmstate(thread);
    00803     if(state != SQ_VMSTATE_SUSPENDED) {
    00804       switch(state) {
    00805         case SQ_VMSTATE_IDLE:
    00806           return sq_throwerror(v,_SC("cannot wakeup a idle thread"));
    00807         break;
    00808         case SQ_VMSTATE_RUNNING:
    00809           return sq_throwerror(v,_SC("cannot wakeup a running thread"));
    00810         break;
    00811       }
    00812     }
    00813
    00814     SQInteger wakeupret = sq_gettop(v)>1?1:0;
    00815     if(wakeupret) {
    00816       sq_move(thread,v,2);
    00817     }
    00818     if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQFalse))) {
    00819       sq_move(v,thread,-1);
    00820       sq_pop(thread,1); //pop retval
    00821       if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
    00822         sq_settop(thread,1); //pop roottable
    00823       }
    00824       return 1;
    00825     }
    00826     sq_settop(thread,1);
    00827     v->_lasterror = thread->_lasterror;
    00828     return SQ_ERROR;
    00829   }
    00830   return sq_throwerror(v,_SC("wrong parameter"));
    00831 }
    00832
    00833 static SQInteger thread_getstatus(HSQUIRRELVM v)
    00834 {
    00835   SQObjectPtr &o = stack_get(v,1);
    00836   switch(sq_getvmstate(_thread(o))) {
    00837     case SQ_VMSTATE_IDLE:
    00838       sq_pushstring(v,_SC("idle"),-1);
    00839     break;
    00840     case SQ_VMSTATE_RUNNING:
    00841       sq_pushstring(v,_SC("running"),-1);
    00842     break;
    00843     case SQ_VMSTATE_SUSPENDED:
    00844       sq_pushstring(v,_SC("suspended"),-1);
    00845     break;
    00846     default:
    00847       return sq_throwerror(v,_SC("internal VM error"));
    00848   }
    00849   return 1;
    00850 }
    00851
    00852 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
    00853   {_SC("call"), thread_call, -1, _SC("v")},
    00854   {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
    00855   {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
    00856   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00857   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00858   {0,0,0,0},
    00859 };
    00860
    00861 static SQInteger class_getattributes(HSQUIRRELVM v)
    00862 {
    00863   if(SQ_SUCCEEDED(sq_getattributes(v,-2)))
    00864     return 1;
    00865   return SQ_ERROR;
    00866 }
    00867
    00868 static SQInteger class_setattributes(HSQUIRRELVM v)
    00869 {
    00870   if(SQ_SUCCEEDED(sq_setattributes(v,-3)))
    00871     return 1;
    00872   return SQ_ERROR;
    00873 }
    00874
    00875 static SQInteger class_instance(HSQUIRRELVM v)
    00876 {
    00877   if(SQ_SUCCEEDED(sq_createinstance(v,-1)))
    00878     return 1;
    00879   return SQ_ERROR;
    00880 }
    00881
    00882 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
    00883   {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
    00884   {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
    00885   {_SC("rawin"),container_rawexists,2, _SC("y")},
    00886   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00887   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00888   {_SC("instance"),class_instance,1, _SC("y")},
    00889   {0,0,0,0}
    00890 };
    00891
    00892 static SQInteger instance_getclass(HSQUIRRELVM v)
    00893 {
    00894   if(SQ_SUCCEEDED(sq_getclass(v,1)))
    00895     return 1;
    00896   return SQ_ERROR;
    00897 }
    00898
    00899 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
    00900   {_SC("getclass"), instance_getclass, 1, _SC("x")},
    00901   {_SC("rawin"),container_rawexists,2, _SC("x")},
    00902   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00903   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00904   {0,0,0,0}
    00905 };
    00906
    00907 static SQInteger weakref_ref(HSQUIRRELVM v)
    00908 {
    00909   if(SQ_FAILED(sq_getweakrefval(v,1)))
    00910     return SQ_ERROR;
    00911   return 1;
    00912 }
    00913
    00914 SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
    00915   {_SC("ref"),weakref_ref,1, _SC("r")},
    00916   {_SC("weakref"),obj_delegate_weakref,1, NULL },
    00917   {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
    00918   {0,0,0,0}
    00919 };
    00920
    00921