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