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