squirrel update
[supertux.git] / src / squirrel / squirrel / sqbaselib.cpp
1 /*\r
2         see copyright notice in squirrel.h\r
3 */\r
4 #include "sqpcheader.h"\r
5 #include "sqvm.h"\r
6 #include "sqstring.h"\r
7 #include "sqtable.h"\r
8 #include "sqarray.h"\r
9 #include "sqfuncproto.h"\r
10 #include "sqclosure.h"\r
11 #include "sqclass.h"\r
12 #include <stdlib.h>\r
13 #include <stdarg.h>\r
14 #include <ctype.h>\r
15 \r
16 bool str2num(const SQChar *s,SQObjectPtr &res)\r
17 {\r
18         SQChar *end;\r
19         if(scstrstr(s,_SC("."))){\r
20                 SQFloat r = SQFloat(scstrtod(s,&end));\r
21                 if(s == end) return false;\r
22                 res = r;\r
23                 return true;\r
24         }\r
25         else{\r
26                 SQInteger r = SQInteger(scstrtol(s,&end,10));\r
27                 if(s == end) return false;\r
28                 res = r;\r
29                 return true;\r
30         }\r
31 }\r
32 \r
33 #ifndef NO_GARBAGE_COLLECTOR\r
34 static SQInteger base_collectgarbage(HSQUIRRELVM v)\r
35 {\r
36         sq_pushinteger(v, sq_collectgarbage(v));\r
37         return 1;\r
38 }\r
39 #endif\r
40 \r
41 static SQInteger base_getroottable(HSQUIRRELVM v)\r
42 {\r
43         v->Push(v->_roottable);\r
44         return 1;\r
45 }\r
46 \r
47 static SQInteger base_setroottable(HSQUIRRELVM v)\r
48 {\r
49         SQObjectPtr &o=stack_get(v,2);\r
50         if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;\r
51         v->Push(o);\r
52         return 1;\r
53 }\r
54 \r
55 static SQInteger base_seterrorhandler(HSQUIRRELVM v)\r
56 {\r
57         sq_seterrorhandler(v);\r
58         return 0;\r
59 }\r
60 \r
61 static SQInteger base_setdebughook(HSQUIRRELVM v)\r
62 {\r
63         sq_setdebughook(v);\r
64         return 0;\r
65 }\r
66 \r
67 static SQInteger base_enabledebuginfo(HSQUIRRELVM v)\r
68 {\r
69         SQObjectPtr &o=stack_get(v,2);\r
70         sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);\r
71         return 0;\r
72 }\r
73 \r
74 static SQInteger base_getstackinfos(HSQUIRRELVM v)\r
75 {\r
76         SQInteger level;\r
77         SQStackInfos si;\r
78         SQInteger seq = 0;\r
79         const SQChar *name = NULL;\r
80         sq_getinteger(v, -1, &level);\r
81         if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))\r
82         {\r
83                 const SQChar *fn = _SC("unknown");\r
84                 const SQChar *src = _SC("unknown");\r
85                 if(si.funcname)fn = si.funcname;\r
86                 if(si.source)src = si.source;\r
87                 sq_newtable(v);\r
88                 sq_pushstring(v, _SC("func"), -1);\r
89                 sq_pushstring(v, fn, -1);\r
90                 sq_createslot(v, -3);\r
91                 sq_pushstring(v, _SC("src"), -1);\r
92                 sq_pushstring(v, src, -1);\r
93                 sq_createslot(v, -3);\r
94                 sq_pushstring(v, _SC("line"), -1);\r
95                 sq_pushinteger(v, si.line);\r
96                 sq_createslot(v, -3);\r
97                 sq_pushstring(v, _SC("locals"), -1);\r
98                 sq_newtable(v);\r
99                 seq=0;\r
100                 while (name = sq_getlocal(v, level, seq)) {\r
101                         sq_pushstring(v, name, -1);\r
102                         sq_push(v, -2);\r
103                         sq_createslot(v, -4);\r
104                         sq_pop(v, 1);\r
105                         seq++;\r
106                 }\r
107                 sq_createslot(v, -3);\r
108                 return 1;\r
109         }\r
110 \r
111         return 0;\r
112 }\r
113 \r
114 static SQInteger base_assert(HSQUIRRELVM v)\r
115 {\r
116         if(v->IsFalse(stack_get(v,2))){\r
117                 return sq_throwerror(v,_SC("assertion failed"));\r
118         }\r
119         return 0;\r
120 }\r
121 \r
122 static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)\r
123 {\r
124         SQInteger top = sq_gettop(v);\r
125         sidx=0;\r
126         eidx=0;\r
127         o=stack_get(v,1);\r
128         SQObjectPtr &start=stack_get(v,2);\r
129         if(type(start)!=OT_NULL && sq_isnumeric(start)){\r
130                 sidx=tointeger(start);\r
131         }\r
132         if(top>2){\r
133                 SQObjectPtr &end=stack_get(v,3);\r
134                 if(sq_isnumeric(end)){\r
135                         eidx=tointeger(end);\r
136                 }\r
137         }\r
138         else {\r
139                 eidx = sq_getsize(v,1);\r
140         }\r
141         return 1;\r
142 }\r
143 \r
144 static SQInteger base_print(HSQUIRRELVM v)\r
145 {\r
146         const SQChar *str;\r
147         sq_tostring(v,2);\r
148         sq_getstring(v,-1,&str);\r
149         if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);\r
150         return 0;\r
151 }\r
152 \r
153 static SQInteger base_compilestring(HSQUIRRELVM v)\r
154 {\r
155         SQInteger nargs=sq_gettop(v);\r
156         const SQChar *src=NULL,*name=_SC("unnamedbuffer");\r
157         SQInteger size;\r
158         sq_getstring(v,2,&src);\r
159         size=sq_getsize(v,2);\r
160         if(nargs>2){\r
161                 sq_getstring(v,3,&name);\r
162         }\r
163         if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))\r
164                 return 1;\r
165         else\r
166                 return SQ_ERROR;\r
167 }\r
168 \r
169 static SQInteger base_newthread(HSQUIRRELVM v)\r
170 {\r
171         SQObjectPtr &func = stack_get(v,2);\r
172         SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;\r
173         HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);\r
174         sq_move(newv,v,-2);\r
175         return 1;\r
176 }\r
177 \r
178 static SQInteger base_suspend(HSQUIRRELVM v)\r
179 {\r
180         return sq_suspendvm(v);\r
181 }\r
182 \r
183 static SQInteger base_array(HSQUIRRELVM v)\r
184 {\r
185         SQArray *a;\r
186         SQObject &size = stack_get(v,2);\r
187         if(sq_gettop(v) > 2) {\r
188                 a = SQArray::Create(_ss(v),0);\r
189                 a->Resize(tointeger(size),stack_get(v,3));\r
190         }\r
191         else {\r
192                 a = SQArray::Create(_ss(v),tointeger(size));\r
193         }\r
194         v->Push(a);\r
195         return 1;\r
196 }\r
197 \r
198 static SQInteger base_type(HSQUIRRELVM v)\r
199 {\r
200         SQObjectPtr &o = stack_get(v,2);\r
201         v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));\r
202         return 1;\r
203 }\r
204 \r
205 static SQRegFunction base_funcs[]={\r
206         //generic\r
207         {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},\r
208         {_SC("setdebughook"),base_setdebughook,2, NULL},\r
209         {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},\r
210         {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},\r
211         {_SC("getroottable"),base_getroottable,1, NULL},\r
212         {_SC("setroottable"),base_setroottable,2, NULL},\r
213         {_SC("assert"),base_assert,2, NULL},\r
214         {_SC("print"),base_print,2, NULL},\r
215         {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},\r
216         {_SC("newthread"),base_newthread,2, _SC(".c")},\r
217         {_SC("suspend"),base_suspend,-1, NULL},\r
218         {_SC("array"),base_array,-2, _SC(".n")},\r
219         {_SC("type"),base_type,2, NULL},\r
220 #ifndef NO_GARBAGE_COLLECTOR\r
221         {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},\r
222 #endif\r
223         {0,0}\r
224 };\r
225 \r
226 void sq_base_register(HSQUIRRELVM v)\r
227 {\r
228         SQInteger i=0;\r
229         sq_pushroottable(v);\r
230         while(base_funcs[i].name!=0) {\r
231                 sq_pushstring(v,base_funcs[i].name,-1);\r
232                 sq_newclosure(v,base_funcs[i].f,0);\r
233                 sq_setnativeclosurename(v,-1,base_funcs[i].name);\r
234                 sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);\r
235                 sq_createslot(v,-3);\r
236                 i++;\r
237         }\r
238         sq_pushstring(v,_SC("_charsize_"),-1);\r
239         sq_pushinteger(v,sizeof(SQChar));\r
240         sq_createslot(v,-3);\r
241         sq_pop(v,1);\r
242 }\r
243 \r
244 static SQInteger default_delegate_len(HSQUIRRELVM v)\r
245 {\r
246         v->Push(SQInteger(sq_getsize(v,1)));\r
247         return 1;\r
248 }\r
249 \r
250 static SQInteger default_delegate_tofloat(HSQUIRRELVM v)\r
251 {\r
252         SQObjectPtr &o=stack_get(v,1);\r
253         switch(type(o)){\r
254         case OT_STRING:{\r
255                 SQObjectPtr res;\r
256                 if(str2num(_stringval(o),res)){\r
257                         v->Push(SQObjectPtr(tofloat(res)));\r
258                         break;\r
259                 }}\r
260                 return sq_throwerror(v, _SC("cannot convert the string"));\r
261                 break;\r
262         case OT_INTEGER:case OT_FLOAT:\r
263                 v->Push(SQObjectPtr(tofloat(o)));\r
264                 break;\r
265         case OT_BOOL:\r
266                 v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));\r
267                 break;\r
268         default:\r
269                 v->Push(_null_);\r
270                 break;\r
271         }\r
272         return 1;\r
273 }\r
274 \r
275 static SQInteger default_delegate_tointeger(HSQUIRRELVM v)\r
276 {\r
277         SQObjectPtr &o=stack_get(v,1);\r
278         switch(type(o)){\r
279         case OT_STRING:{\r
280                 SQObjectPtr res;\r
281                 if(str2num(_stringval(o),res)){\r
282                         v->Push(SQObjectPtr(tointeger(res)));\r
283                         break;\r
284                 }}\r
285                 return sq_throwerror(v, _SC("cannot convert the string"));\r
286                 break;\r
287         case OT_INTEGER:case OT_FLOAT:\r
288                 v->Push(SQObjectPtr(tointeger(o)));\r
289                 break;\r
290         case OT_BOOL:\r
291                 v->Push(SQObjectPtr(_integer(o)?1:0));\r
292                 break;\r
293         default:\r
294                 v->Push(_null_);\r
295                 break;\r
296         }\r
297         return 1;\r
298 }\r
299 \r
300 static SQInteger default_delegate_tostring(HSQUIRRELVM v)\r
301 {\r
302         sq_tostring(v,1);\r
303         return 1;\r
304 }\r
305 \r
306 static SQInteger obj_delegate_weakref(HSQUIRRELVM v)\r
307 {\r
308         sq_weakref(v,1);\r
309         return 1;\r
310 }\r
311 \r
312 static SQInteger number_delegate_tochar(HSQUIRRELVM v)\r
313 {\r
314         SQObject &o=stack_get(v,1);\r
315         SQChar c=tointeger(o);\r
316         v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));\r
317         return 1;\r
318 }\r
319 \r
320 \r
321 /////////////////////////////////////////////////////////////////\r
322 //TABLE DEFAULT DELEGATE\r
323 \r
324 static SQInteger table_rawdelete(HSQUIRRELVM v)\r
325 {\r
326         if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))\r
327                 return SQ_ERROR;\r
328         return 1;\r
329 }\r
330 \r
331 \r
332 static SQInteger container_rawexists(HSQUIRRELVM v)\r
333 {\r
334         if(SQ_SUCCEEDED(sq_rawget(v,-2))) {\r
335                 sq_pushbool(v,SQTrue);\r
336                 return 1;\r
337         }\r
338         sq_pushbool(v,SQFalse);\r
339         return 1;\r
340 }\r
341 \r
342 static SQInteger table_rawset(HSQUIRRELVM v)\r
343 {\r
344         return sq_rawset(v,-3);\r
345 }\r
346 \r
347 \r
348 static SQInteger table_rawget(HSQUIRRELVM v)\r
349 {\r
350         return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
351 }\r
352 \r
353 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={\r
354         {_SC("len"),default_delegate_len,1, _SC("t")},\r
355         {_SC("rawget"),table_rawget,2, _SC("t")},\r
356         {_SC("rawset"),table_rawset,3, _SC("t")},\r
357         {_SC("rawdelete"),table_rawdelete,2, _SC("t")},\r
358         {_SC("rawin"),container_rawexists,2, _SC("t")},\r
359         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
360         {0,0}\r
361 };\r
362 \r
363 //ARRAY DEFAULT DELEGATE///////////////////////////////////////\r
364 \r
365 static SQInteger array_append(HSQUIRRELVM v)\r
366 {\r
367         return sq_arrayappend(v,-2);\r
368 }\r
369 \r
370 static SQInteger array_extend(HSQUIRRELVM v)\r
371 {\r
372         _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));\r
373         return 0;\r
374 }\r
375 \r
376 static SQInteger array_reverse(HSQUIRRELVM v)\r
377 {\r
378         return sq_arrayreverse(v,-1);\r
379 }\r
380 \r
381 static SQInteger array_pop(HSQUIRRELVM v)\r
382 {\r
383         return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;\r
384 }\r
385 \r
386 static SQInteger array_top(HSQUIRRELVM v)\r
387 {\r
388         SQObject &o=stack_get(v,1);\r
389         if(_array(o)->Size()>0){\r
390                 v->Push(_array(o)->Top());\r
391                 return 1;\r
392         }\r
393         else return sq_throwerror(v,_SC("top() on a empty array"));\r
394 }\r
395 \r
396 static SQInteger array_insert(HSQUIRRELVM v)\r
397 {\r
398         SQObject &o=stack_get(v,1);\r
399         SQObject &idx=stack_get(v,2);\r
400         SQObject &val=stack_get(v,3);\r
401         _array(o)->Insert(idx,val);\r
402         return 0;\r
403 }\r
404 \r
405 static SQInteger array_remove(HSQUIRRELVM v)\r
406 {\r
407         SQObject &o = stack_get(v, 1);\r
408         SQObject &idx = stack_get(v, 2);\r
409         if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));\r
410         SQObjectPtr val;\r
411         if(_array(o)->Get(tointeger(idx), val)) {\r
412                 _array(o)->Remove(tointeger(idx));\r
413                 v->Push(val);\r
414                 return 1;\r
415         }\r
416         return sq_throwerror(v, _SC("idx out of range"));\r
417 }\r
418 \r
419 static SQInteger array_resize(HSQUIRRELVM v)\r
420 {\r
421         SQObject &o = stack_get(v, 1);\r
422         SQObject &nsize = stack_get(v, 2);\r
423         SQObjectPtr fill;\r
424         if(sq_isnumeric(nsize)) {\r
425                 if(sq_gettop(v) > 2)\r
426                         fill = stack_get(v, 3);\r
427                 _array(o)->Resize(tointeger(nsize),fill);\r
428                 return 0;\r
429         }\r
430         return sq_throwerror(v, _SC("size must be a number"));\r
431 }\r
432 \r
433 \r
434 //QSORT ala Sedgewick\r
435 bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)\r
436 {\r
437         if(func < 0) {\r
438                 if(!v->ObjCmp(a,b,ret)) return false;\r
439         }\r
440         else {\r
441                 SQInteger top = sq_gettop(v);\r
442                 sq_push(v, func);\r
443                 sq_pushroottable(v);\r
444                 v->Push(a);\r
445                 v->Push(b);\r
446                 if(SQ_FAILED(sq_call(v, 3, SQTrue))) {\r
447                         v->Raise_Error(_SC("compare func failed"));\r
448                         return false;\r
449                 }\r
450                 sq_getinteger(v, -1, &ret);\r
451                 sq_settop(v, top);\r
452                 return true;\r
453         }\r
454         return true;\r
455 }\r
456 //QSORT ala Sedgewick\r
457 bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)\r
458 {\r
459         SQInteger i, j;\r
460         SQArray *a=_array(arr);\r
461         SQObjectPtr pivot,t;\r
462         if( l < r ){\r
463                 pivot = a->_values[l];\r
464                 i = l; j = r+1;\r
465                 while(1){\r
466                         SQInteger ret;\r
467                         do { \r
468                                 ++i; \r
469                                 if(i > r) break;\r
470                                 if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))\r
471                                         return false;\r
472                         } while( ret <= 0);\r
473                         do {\r
474                                 --j; \r
475                                 if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))\r
476                                         return false;\r
477                         }\r
478                         while( ret > 0 );\r
479                         if( i >= j ) break;\r
480                         t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;\r
481                 }\r
482                 t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;\r
483                 if(!_qsort( v, arr, l, j-1,func)) return false;\r
484                 if(!_qsort( v, arr, j+1, r,func)) return false;\r
485         }\r
486         return true;\r
487 }\r
488 \r
489 static SQInteger array_sort(HSQUIRRELVM v)\r
490 {\r
491         //SQ_TRY {\r
492         SQInteger func = -1;\r
493         SQObjectPtr &o = stack_get(v,1);\r
494         SQObject &funcobj = stack_get(v,2);\r
495         if(_array(o)->Size() > 1) {\r
496                 if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;\r
497                 if(!_qsort(v, o, 0, _array(o)->Size()-1, func))\r
498                         return SQ_ERROR;\r
499 \r
500         }\r
501         return 0;\r
502 }\r
503 static SQInteger array_slice(HSQUIRRELVM v)\r
504 {\r
505         SQInteger sidx,eidx;\r
506         SQObjectPtr o;\r
507         if(get_slice_params(v,sidx,eidx,o)==-1)return -1;\r
508         if(sidx<0)sidx=_array(o)->Size()+sidx;\r
509         if(eidx<0)eidx=_array(o)->Size()+eidx;\r
510         if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));\r
511         SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);\r
512         SQObjectPtr t;\r
513         SQInteger count=0;\r
514         for(SQInteger i=sidx;i<eidx;i++){\r
515                 _array(o)->Get(i,t);\r
516                 arr->Set(count++,t);\r
517         }\r
518         v->Push(arr);\r
519         return 1;\r
520         \r
521 }\r
522 \r
523 SQRegFunction SQSharedState::_array_default_delegate_funcz[]={\r
524         {_SC("len"),default_delegate_len,1, _SC("a")},\r
525         {_SC("append"),array_append,2, _SC("a")},\r
526         {_SC("extend"),array_extend,2, _SC("aa")},\r
527         {_SC("push"),array_append,2, _SC("a")},\r
528         {_SC("pop"),array_pop,1, _SC("a")},\r
529         {_SC("top"),array_top,1, _SC("a")},\r
530         {_SC("insert"),array_insert,3, _SC("an")},\r
531         {_SC("remove"),array_remove,2, _SC("an")},\r
532         {_SC("resize"),array_resize,-2, _SC("an")},\r
533         {_SC("reverse"),array_reverse,1, _SC("a")},\r
534         {_SC("sort"),array_sort,-1, _SC("ac")},\r
535         {_SC("slice"),array_slice,-1, _SC("ann")},\r
536         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
537         {0,0}\r
538 };\r
539 \r
540 //STRING DEFAULT DELEGATE//////////////////////////\r
541 static SQInteger string_slice(HSQUIRRELVM v)\r
542 {\r
543         SQInteger sidx,eidx;\r
544         SQObjectPtr o;\r
545         if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;\r
546         if(sidx<0)sidx=_string(o)->_len+sidx;\r
547         if(eidx<0)eidx=_string(o)->_len+eidx;\r
548         if(eidx<sidx)\r
549                 return sq_throwerror(v,_SC("wrong indexes"));\r
550         v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));\r
551         return 1;\r
552 }\r
553 \r
554 static SQInteger string_find(HSQUIRRELVM v)\r
555 {\r
556         SQInteger top,start_idx=0;\r
557         const SQChar *str,*substr,*ret;\r
558         if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){\r
559                 if(top>2)sq_getinteger(v,3,&start_idx);\r
560                 if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){\r
561                         ret=scstrstr(&str[start_idx],substr);\r
562                         if(ret){\r
563                                 sq_pushinteger(v,(SQInteger)(ret-str));\r
564                                 return 1;\r
565                         }\r
566                 }\r
567                 return 0;\r
568         }\r
569         return sq_throwerror(v,_SC("invalid param"));\r
570 }\r
571 \r
572 #define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \\r
573 { \\r
574         SQObject str=stack_get(v,1); \\r
575         SQInteger len=_string(str)->_len; \\r
576         const SQChar *sThis=_stringval(str); \\r
577         SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \\r
578         for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \\r
579         v->Push(SQString::Create(_ss(v),sNew,len)); \\r
580         return 1; \\r
581 }\r
582 \r
583 \r
584 STRING_TOFUNCZ(tolower)\r
585 STRING_TOFUNCZ(toupper)\r
586 \r
587 SQRegFunction SQSharedState::_string_default_delegate_funcz[]={\r
588         {_SC("len"),default_delegate_len,1, _SC("s")},\r
589         {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},\r
590         {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},\r
591         {_SC("tostring"),default_delegate_tostring,1, _SC("s")},\r
592         {_SC("slice"),string_slice,-1, _SC(" s n  n")},\r
593         {_SC("find"),string_find,-2, _SC("s s n ")},\r
594         {_SC("tolower"),string_tolower,1, _SC("s")},\r
595         {_SC("toupper"),string_toupper,1, _SC("s")},\r
596         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
597         {0,0}\r
598 };\r
599 \r
600 //INTEGER DEFAULT DELEGATE//////////////////////////\r
601 SQRegFunction SQSharedState::_number_default_delegate_funcz[]={\r
602         {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},\r
603         {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},\r
604         {_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},\r
605         {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},\r
606         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
607         {0,0}\r
608 };\r
609 \r
610 //CLOSURE DEFAULT DELEGATE//////////////////////////\r
611 static SQInteger closure_call(HSQUIRRELVM v)\r
612 {\r
613         return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue))?1:SQ_ERROR;\r
614 }\r
615 \r
616 static SQInteger closure_acall(HSQUIRRELVM v)\r
617 {\r
618         SQArray *aparams=_array(stack_get(v,2));\r
619         SQInteger nparams=aparams->Size();\r
620         v->Push(stack_get(v,1));\r
621         for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);\r
622         return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue))?1:SQ_ERROR;\r
623 }\r
624 \r
625 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
626         {_SC("call"),closure_call,-1, _SC("c")},\r
627         {_SC("acall"),closure_acall,2, _SC("ca")},\r
628         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
629         {0,0}\r
630 };\r
631 \r
632 //GENERATOR DEFAULT DELEGATE\r
633 static SQInteger generator_getstatus(HSQUIRRELVM v)\r
634 {\r
635         SQObject &o=stack_get(v,1);\r
636         switch(_generator(o)->_state){\r
637                 case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;\r
638                 case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;\r
639                 case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;\r
640         }\r
641         return 1;\r
642 }\r
643 \r
644 SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={\r
645         {_SC("getstatus"),generator_getstatus,1, _SC("g")},\r
646         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
647         {0,0}\r
648 };\r
649 \r
650 //THREAD DEFAULT DELEGATE\r
651 \r
652 static SQInteger thread_call(HSQUIRRELVM v)\r
653 {\r
654         SQObjectPtr o = stack_get(v,1);\r
655         if(type(o) == OT_THREAD) {\r
656                 SQInteger nparams = sq_gettop(v);\r
657                 _thread(o)->Push(_thread(o)->_roottable);\r
658                 for(SQInteger i = 2; i<(nparams+1); i++)\r
659                         sq_move(_thread(o),v,i);\r
660                 if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue))) {\r
661                         sq_move(v,_thread(o),-1);\r
662                         return 1;\r
663                 }\r
664                 return SQ_ERROR;\r
665         }\r
666         return sq_throwerror(v,_SC("wrong parameter"));\r
667 }\r
668 \r
669 static SQInteger thread_wakeup(HSQUIRRELVM v)\r
670 {\r
671         SQObjectPtr o = stack_get(v,1);\r
672         if(type(o) == OT_THREAD) {\r
673                 SQVM *thread = _thread(o);\r
674                 SQInteger state = sq_getvmstate(thread);\r
675                 if(state != SQ_VMSTATE_SUSPENDED) {\r
676                         switch(state) {\r
677                                 case SQ_VMSTATE_IDLE:\r
678                                         return sq_throwerror(v,_SC("cannot wakeup a idle thread"));\r
679                                 break;\r
680                                 case SQ_VMSTATE_RUNNING:\r
681                                         return sq_throwerror(v,_SC("cannot wakeup a running thread"));\r
682                                 break;\r
683                         }\r
684                 }\r
685                         \r
686                 SQInteger wakeupret = sq_gettop(v)>1?1:0;\r
687                 if(wakeupret) {\r
688                         sq_move(thread,v,2);\r
689                 }\r
690                 if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1))) {\r
691                         sq_move(v,thread,-1);\r
692                         sq_pop(thread,1);\r
693                         if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {\r
694                                 sq_pop(thread,1);\r
695                         }\r
696                         return 1;\r
697                 }\r
698                 return SQ_ERROR;\r
699         }\r
700         return sq_throwerror(v,_SC("wrong parameter"));\r
701 }\r
702 \r
703 static SQInteger thread_getstatus(HSQUIRRELVM v)\r
704 {\r
705         SQObjectPtr &o = stack_get(v,1);\r
706         switch(sq_getvmstate(_thread(o))) {\r
707                 case SQ_VMSTATE_IDLE:\r
708                         sq_pushstring(v,_SC("idle"),-1);\r
709                 break;\r
710                 case SQ_VMSTATE_RUNNING:\r
711                         sq_pushstring(v,_SC("running"),-1);\r
712                 break;\r
713                 case SQ_VMSTATE_SUSPENDED:\r
714                         sq_pushstring(v,_SC("suspended"),-1);\r
715                 break;\r
716                 default:\r
717                         return sq_throwerror(v,_SC("internal VM error"));\r
718         }\r
719         return 1;\r
720 }\r
721 \r
722 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {\r
723         {_SC("call"), thread_call, -1, _SC("v")},\r
724         {_SC("wakeup"), thread_wakeup, -1, _SC("v")},\r
725         {_SC("getstatus"), thread_getstatus, 1, _SC("v")},\r
726         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
727         {0,0},\r
728 };\r
729 \r
730 static SQInteger class_getattributes(HSQUIRRELVM v)\r
731 {\r
732         if(SQ_SUCCEEDED(sq_getattributes(v,-2)))\r
733                 return 1;\r
734         return SQ_ERROR;\r
735 }\r
736 \r
737 static SQInteger class_setattributes(HSQUIRRELVM v)\r
738 {\r
739         if(SQ_SUCCEEDED(sq_setattributes(v,-3)))\r
740                 return 1;\r
741         return SQ_ERROR;\r
742 }\r
743 \r
744 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {\r
745         {_SC("getattributes"), class_getattributes, 2, _SC("y.")},\r
746         {_SC("setattributes"), class_setattributes, 3, _SC("y..")},\r
747         {_SC("rawin"),container_rawexists,2, _SC("y")},\r
748         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
749         {0,0}\r
750 };\r
751 \r
752 static SQInteger instance_getclass(HSQUIRRELVM v)\r
753 {\r
754         if(SQ_SUCCEEDED(sq_getclass(v,1)))\r
755                 return 1;\r
756         return SQ_ERROR;\r
757 }\r
758 \r
759 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {\r
760         {_SC("getclass"), instance_getclass, 1, _SC("x")},\r
761         {_SC("rawin"),container_rawexists,2, _SC("x")},\r
762         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
763         {0,0}\r
764 };\r
765 \r
766 static SQInteger weakref_ref(HSQUIRRELVM v)\r
767 {\r
768         if(SQ_FAILED(sq_getweakrefval(v,1)))\r
769                 return SQ_ERROR;\r
770         return 1;\r
771 }\r
772 \r
773 SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {\r
774         {_SC("ref"),weakref_ref,1, _SC("r")},\r
775         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
776         {0,0}\r
777 };\r
778 \r
779 \r