Updated addon repository URL and improved debug output on download
[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         const SQChar *e = s;\r
20         SQBool isfloat = SQFalse;\r
21         SQChar c;\r
22         while((c = *e) != _SC('\0'))\r
23         {\r
24                 if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation\r
25                         isfloat = SQTrue;\r
26                         break;\r
27                 }\r
28                 e++;\r
29         }\r
30         if(isfloat){\r
31                 SQFloat r = SQFloat(scstrtod(s,&end));\r
32                 if(s == end) return false;\r
33                 res = r;\r
34         }\r
35         else{\r
36                 SQInteger r = SQInteger(scstrtol(s,&end,10));\r
37                 if(s == end) return false;\r
38                 res = r;\r
39         }\r
40         return true;\r
41 }\r
42 \r
43 static SQInteger base_dummy(HSQUIRRELVM v)\r
44 {\r
45         return 0;\r
46 }\r
47 \r
48 #ifndef NO_GARBAGE_COLLECTOR\r
49 static SQInteger base_collectgarbage(HSQUIRRELVM v)\r
50 {\r
51         sq_pushinteger(v, sq_collectgarbage(v));\r
52         return 1;\r
53 }\r
54 static SQInteger base_resurectureachable(HSQUIRRELVM v)\r
55 {\r
56         sq_resurrectunreachable(v);\r
57         return 1;\r
58 }\r
59 #endif\r
60 \r
61 static SQInteger base_getroottable(HSQUIRRELVM v)\r
62 {\r
63         v->Push(v->_roottable);\r
64         return 1;\r
65 }\r
66 \r
67 static SQInteger base_getconsttable(HSQUIRRELVM v)\r
68 {\r
69         v->Push(_ss(v)->_consts);\r
70         return 1;\r
71 }\r
72 \r
73 \r
74 static SQInteger base_setroottable(HSQUIRRELVM v)\r
75 {\r
76         SQObjectPtr o = v->_roottable;\r
77         if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;\r
78         v->Push(o);\r
79         return 1;\r
80 }\r
81 \r
82 static SQInteger base_setconsttable(HSQUIRRELVM v)\r
83 {\r
84         SQObjectPtr o = _ss(v)->_consts;\r
85         if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;\r
86         v->Push(o);\r
87         return 1;\r
88 }\r
89 \r
90 static SQInteger base_seterrorhandler(HSQUIRRELVM v)\r
91 {\r
92         sq_seterrorhandler(v);\r
93         return 0;\r
94 }\r
95 \r
96 static SQInteger base_setdebughook(HSQUIRRELVM v)\r
97 {\r
98         sq_setdebughook(v);\r
99         return 0;\r
100 }\r
101 \r
102 static SQInteger base_enabledebuginfo(HSQUIRRELVM v)\r
103 {\r
104         SQObjectPtr &o=stack_get(v,2);\r
105         \r
106         sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue);\r
107         return 0;\r
108 }\r
109 \r
110 static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)\r
111 {\r
112         SQStackInfos si;\r
113         SQInteger seq = 0;\r
114         const SQChar *name = NULL;\r
115         \r
116         if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))\r
117         {\r
118                 const SQChar *fn = _SC("unknown");\r
119                 const SQChar *src = _SC("unknown");\r
120                 if(si.funcname)fn = si.funcname;\r
121                 if(si.source)src = si.source;\r
122                 sq_newtable(v);\r
123                 sq_pushstring(v, _SC("func"), -1);\r
124                 sq_pushstring(v, fn, -1);\r
125                 sq_newslot(v, -3, SQFalse);\r
126                 sq_pushstring(v, _SC("src"), -1);\r
127                 sq_pushstring(v, src, -1);\r
128                 sq_newslot(v, -3, SQFalse);\r
129                 sq_pushstring(v, _SC("line"), -1);\r
130                 sq_pushinteger(v, si.line);\r
131                 sq_newslot(v, -3, SQFalse);\r
132                 sq_pushstring(v, _SC("locals"), -1);\r
133                 sq_newtable(v);\r
134                 seq=0;\r
135                 while ((name = sq_getlocal(v, level, seq))) {\r
136                         sq_pushstring(v, name, -1);\r
137                         sq_push(v, -2);\r
138                         sq_newslot(v, -4, SQFalse);\r
139                         sq_pop(v, 1);\r
140                         seq++;\r
141                 }\r
142                 sq_newslot(v, -3, SQFalse);\r
143                 return 1;\r
144         }\r
145 \r
146         return 0;\r
147 }\r
148 static SQInteger base_getstackinfos(HSQUIRRELVM v)\r
149 {\r
150         SQInteger level;\r
151         sq_getinteger(v, -1, &level);\r
152         return __getcallstackinfos(v,level);\r
153 }\r
154 \r
155 static SQInteger base_assert(HSQUIRRELVM v)\r
156 {\r
157         if(SQVM::IsFalse(stack_get(v,2))){\r
158                 return sq_throwerror(v,_SC("assertion failed"));\r
159         }\r
160         return 0;\r
161 }\r
162 \r
163 static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)\r
164 {\r
165         SQInteger top = sq_gettop(v);\r
166         sidx=0;\r
167         eidx=0;\r
168         o=stack_get(v,1);\r
169         SQObjectPtr &start=stack_get(v,2);\r
170         if(type(start)!=OT_NULL && sq_isnumeric(start)){\r
171                 sidx=tointeger(start);\r
172         }\r
173         if(top>2){\r
174                 SQObjectPtr &end=stack_get(v,3);\r
175                 if(sq_isnumeric(end)){\r
176                         eidx=tointeger(end);\r
177                 }\r
178         }\r
179         else {\r
180                 eidx = sq_getsize(v,1);\r
181         }\r
182         return 1;\r
183 }\r
184 \r
185 static SQInteger base_print(HSQUIRRELVM v)\r
186 {\r
187         const SQChar *str;\r
188         if(SQ_SUCCEEDED(sq_tostring(v,2)))\r
189         {\r
190                 if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {\r
191                         if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);\r
192                         return 0;\r
193                 }\r
194         }\r
195         return SQ_ERROR;\r
196 }\r
197 \r
198 static SQInteger base_error(HSQUIRRELVM v)\r
199 {\r
200         const SQChar *str;\r
201         if(SQ_SUCCEEDED(sq_tostring(v,2)))\r
202         {\r
203                 if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {\r
204                         if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);\r
205                         return 0;\r
206                 }\r
207         }\r
208         return SQ_ERROR;\r
209 }\r
210 \r
211 static SQInteger base_compilestring(HSQUIRRELVM v)\r
212 {\r
213         SQInteger nargs=sq_gettop(v);\r
214         const SQChar *src=NULL,*name=_SC("unnamedbuffer");\r
215         SQInteger size;\r
216         sq_getstring(v,2,&src);\r
217         size=sq_getsize(v,2);\r
218         if(nargs>2){\r
219                 sq_getstring(v,3,&name);\r
220         }\r
221         if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))\r
222                 return 1;\r
223         else\r
224                 return SQ_ERROR;\r
225 }\r
226 \r
227 static SQInteger base_newthread(HSQUIRRELVM v)\r
228 {\r
229         SQObjectPtr &func = stack_get(v,2);\r
230         SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;\r
231         HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);\r
232         sq_move(newv,v,-2);\r
233         return 1;\r
234 }\r
235 \r
236 static SQInteger base_suspend(HSQUIRRELVM v)\r
237 {\r
238         return sq_suspendvm(v);\r
239 }\r
240 \r
241 static SQInteger base_array(HSQUIRRELVM v)\r
242 {\r
243         SQArray *a;\r
244         SQObject &size = stack_get(v,2);\r
245         if(sq_gettop(v) > 2) {\r
246                 a = SQArray::Create(_ss(v),0);\r
247                 a->Resize(tointeger(size),stack_get(v,3));\r
248         }\r
249         else {\r
250                 a = SQArray::Create(_ss(v),tointeger(size));\r
251         }\r
252         v->Push(a);\r
253         return 1;\r
254 }\r
255 \r
256 static SQInteger base_type(HSQUIRRELVM v)\r
257 {\r
258         SQObjectPtr &o = stack_get(v,2);\r
259         v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));\r
260         return 1;\r
261 }\r
262 \r
263 static SQInteger base_callee(HSQUIRRELVM v)\r
264 {\r
265         if(v->_callsstacksize > 1)\r
266         {\r
267                 v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);\r
268                 return 1;\r
269         }\r
270         return sq_throwerror(v,_SC("no closure in the calls stack"));\r
271 }\r
272 \r
273 static SQRegFunction base_funcs[]={\r
274         //generic\r
275         {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},\r
276         {_SC("setdebughook"),base_setdebughook,2, NULL},\r
277         {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},\r
278         {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},\r
279         {_SC("getroottable"),base_getroottable,1, NULL},\r
280         {_SC("setroottable"),base_setroottable,2, NULL},\r
281         {_SC("getconsttable"),base_getconsttable,1, NULL},\r
282         {_SC("setconsttable"),base_setconsttable,2, NULL},\r
283         {_SC("assert"),base_assert,2, NULL},\r
284         {_SC("print"),base_print,2, NULL},\r
285         {_SC("error"),base_error,2, NULL},\r
286         {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},\r
287         {_SC("newthread"),base_newthread,2, _SC(".c")},\r
288         {_SC("suspend"),base_suspend,-1, NULL},\r
289         {_SC("array"),base_array,-2, _SC(".n")},\r
290         {_SC("type"),base_type,2, NULL},\r
291         {_SC("callee"),base_callee,0,NULL},\r
292         {_SC("dummy"),base_dummy,0,NULL},\r
293 #ifndef NO_GARBAGE_COLLECTOR\r
294         {_SC("collectgarbage"),base_collectgarbage,0, NULL},\r
295         {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},\r
296 #endif\r
297         {0,0}\r
298 };\r
299 \r
300 void sq_base_register(HSQUIRRELVM v)\r
301 {\r
302         SQInteger i=0;\r
303         sq_pushroottable(v);\r
304         while(base_funcs[i].name!=0) {\r
305                 sq_pushstring(v,base_funcs[i].name,-1);\r
306                 sq_newclosure(v,base_funcs[i].f,0);\r
307                 sq_setnativeclosurename(v,-1,base_funcs[i].name);\r
308                 sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);\r
309                 sq_newslot(v,-3, SQFalse);\r
310                 i++;\r
311         }\r
312         \r
313         sq_pushstring(v,_SC("_versionnumber_"),-1);\r
314         sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);\r
315         sq_newslot(v,-3, SQFalse);\r
316         sq_pushstring(v,_SC("_version_"),-1);\r
317         sq_pushstring(v,SQUIRREL_VERSION,-1);\r
318         sq_newslot(v,-3, SQFalse);\r
319         sq_pushstring(v,_SC("_charsize_"),-1);\r
320         sq_pushinteger(v,sizeof(SQChar));\r
321         sq_newslot(v,-3, SQFalse);\r
322         sq_pushstring(v,_SC("_intsize_"),-1);\r
323         sq_pushinteger(v,sizeof(SQInteger));\r
324         sq_newslot(v,-3, SQFalse);\r
325         sq_pushstring(v,_SC("_floatsize_"),-1);\r
326         sq_pushinteger(v,sizeof(SQFloat));\r
327         sq_newslot(v,-3, SQFalse);\r
328         sq_pop(v,1);\r
329 }\r
330 \r
331 static SQInteger default_delegate_len(HSQUIRRELVM v)\r
332 {\r
333         v->Push(SQInteger(sq_getsize(v,1)));\r
334         return 1;\r
335 }\r
336 \r
337 static SQInteger default_delegate_tofloat(HSQUIRRELVM v)\r
338 {\r
339         SQObjectPtr &o=stack_get(v,1);\r
340         switch(type(o)){\r
341         case OT_STRING:{\r
342                 SQObjectPtr res;\r
343                 if(str2num(_stringval(o),res)){\r
344                         v->Push(SQObjectPtr(tofloat(res)));\r
345                         break;\r
346                 }}\r
347                 return sq_throwerror(v, _SC("cannot convert the string"));\r
348                 break;\r
349         case OT_INTEGER:case OT_FLOAT:\r
350                 v->Push(SQObjectPtr(tofloat(o)));\r
351                 break;\r
352         case OT_BOOL:\r
353                 v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));\r
354                 break;\r
355         default:\r
356                 v->PushNull();\r
357                 break;\r
358         }\r
359         return 1;\r
360 }\r
361 \r
362 static SQInteger default_delegate_tointeger(HSQUIRRELVM v)\r
363 {\r
364         SQObjectPtr &o=stack_get(v,1);\r
365         switch(type(o)){\r
366         case OT_STRING:{\r
367                 SQObjectPtr res;\r
368                 if(str2num(_stringval(o),res)){\r
369                         v->Push(SQObjectPtr(tointeger(res)));\r
370                         break;\r
371                 }}\r
372                 return sq_throwerror(v, _SC("cannot convert the string"));\r
373                 break;\r
374         case OT_INTEGER:case OT_FLOAT:\r
375                 v->Push(SQObjectPtr(tointeger(o)));\r
376                 break;\r
377         case OT_BOOL:\r
378                 v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));\r
379                 break;\r
380         default:\r
381                 v->PushNull();\r
382                 break;\r
383         }\r
384         return 1;\r
385 }\r
386 \r
387 static SQInteger default_delegate_tostring(HSQUIRRELVM v)\r
388 {\r
389         if(SQ_FAILED(sq_tostring(v,1))) \r
390                 return SQ_ERROR;\r
391         return 1;\r
392 }\r
393 \r
394 static SQInteger obj_delegate_weakref(HSQUIRRELVM v)\r
395 {\r
396         sq_weakref(v,1);\r
397         return 1;\r
398 }\r
399 \r
400 static SQInteger obj_clear(HSQUIRRELVM v)\r
401 {\r
402         return sq_clear(v,-1);\r
403 }\r
404 \r
405 \r
406 static SQInteger number_delegate_tochar(HSQUIRRELVM v)\r
407 {\r
408         SQObject &o=stack_get(v,1);\r
409         SQChar c = (SQChar)tointeger(o);\r
410         v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));\r
411         return 1;\r
412 }\r
413 \r
414 \r
415 \r
416 /////////////////////////////////////////////////////////////////\r
417 //TABLE DEFAULT DELEGATE\r
418 \r
419 static SQInteger table_rawdelete(HSQUIRRELVM v)\r
420 {\r
421         if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))\r
422                 return SQ_ERROR;\r
423         return 1;\r
424 }\r
425 \r
426 \r
427 static SQInteger container_rawexists(HSQUIRRELVM v)\r
428 {\r
429         if(SQ_SUCCEEDED(sq_rawget(v,-2))) {\r
430                 sq_pushbool(v,SQTrue);\r
431                 return 1;\r
432         }\r
433         sq_pushbool(v,SQFalse);\r
434         return 1;\r
435 }\r
436 \r
437 static SQInteger container_rawset(HSQUIRRELVM v)\r
438 {\r
439         return sq_rawset(v,-3);\r
440 }\r
441 \r
442 \r
443 static SQInteger container_rawget(HSQUIRRELVM v)\r
444 {\r
445         return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
446 }\r
447 \r
448 static SQInteger table_setdelegate(HSQUIRRELVM v)\r
449 {\r
450         if(SQ_FAILED(sq_setdelegate(v,-2)))\r
451                 return SQ_ERROR;\r
452         sq_push(v,-1); // -1 because sq_setdelegate pops 1\r
453         return 1;\r
454 }\r
455 \r
456 static SQInteger table_getdelegate(HSQUIRRELVM v)\r
457 {\r
458         return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;\r
459 }\r
460 \r
461 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={\r
462         {_SC("len"),default_delegate_len,1, _SC("t")},\r
463         {_SC("rawget"),container_rawget,2, _SC("t")},\r
464         {_SC("rawset"),container_rawset,3, _SC("t")},\r
465         {_SC("rawdelete"),table_rawdelete,2, _SC("t")},\r
466         {_SC("rawin"),container_rawexists,2, _SC("t")},\r
467         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
468         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
469         {_SC("clear"),obj_clear,1, _SC(".")},\r
470         {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},\r
471         {_SC("getdelegate"),table_getdelegate,1, _SC(".")},\r
472         {0,0}\r
473 };\r
474 \r
475 //ARRAY DEFAULT DELEGATE///////////////////////////////////////\r
476 \r
477 static SQInteger array_append(HSQUIRRELVM v)\r
478 {\r
479         return sq_arrayappend(v,-2);\r
480 }\r
481 \r
482 static SQInteger array_extend(HSQUIRRELVM v)\r
483 {\r
484         _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));\r
485         return 0;\r
486 }\r
487 \r
488 static SQInteger array_reverse(HSQUIRRELVM v)\r
489 {\r
490         return sq_arrayreverse(v,-1);\r
491 }\r
492 \r
493 static SQInteger array_pop(HSQUIRRELVM v)\r
494 {\r
495         return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;\r
496 }\r
497 \r
498 static SQInteger array_top(HSQUIRRELVM v)\r
499 {\r
500         SQObject &o=stack_get(v,1);\r
501         if(_array(o)->Size()>0){\r
502                 v->Push(_array(o)->Top());\r
503                 return 1;\r
504         }\r
505         else return sq_throwerror(v,_SC("top() on a empty array"));\r
506 }\r
507 \r
508 static SQInteger array_insert(HSQUIRRELVM v)\r
509 {\r
510         SQObject &o=stack_get(v,1);\r
511         SQObject &idx=stack_get(v,2);\r
512         SQObject &val=stack_get(v,3);\r
513         if(!_array(o)->Insert(tointeger(idx),val))\r
514                 return sq_throwerror(v,_SC("index out of range"));\r
515         return 0;\r
516 }\r
517 \r
518 static SQInteger array_remove(HSQUIRRELVM v)\r
519 {\r
520         SQObject &o = stack_get(v, 1);\r
521         SQObject &idx = stack_get(v, 2);\r
522         if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));\r
523         SQObjectPtr val;\r
524         if(_array(o)->Get(tointeger(idx), val)) {\r
525                 _array(o)->Remove(tointeger(idx));\r
526                 v->Push(val);\r
527                 return 1;\r
528         }\r
529         return sq_throwerror(v, _SC("idx out of range"));\r
530 }\r
531 \r
532 static SQInteger array_resize(HSQUIRRELVM v)\r
533 {\r
534         SQObject &o = stack_get(v, 1);\r
535         SQObject &nsize = stack_get(v, 2);\r
536         SQObjectPtr fill;\r
537         if(sq_isnumeric(nsize)) {\r
538                 if(sq_gettop(v) > 2)\r
539                         fill = stack_get(v, 3);\r
540                 _array(o)->Resize(tointeger(nsize),fill);\r
541                 return 0;\r
542         }\r
543         return sq_throwerror(v, _SC("size must be a number"));\r
544 }\r
545 \r
546 static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {\r
547         SQObjectPtr temp;\r
548         SQInteger size = src->Size();\r
549         for(SQInteger n = 0; n < size; n++) {\r
550                 src->Get(n,temp);\r
551                 v->Push(src);\r
552                 v->Push(temp);\r
553                 if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {\r
554                         return SQ_ERROR;\r
555                 }\r
556                 dest->Set(n,v->GetUp(-1));\r
557                 v->Pop();\r
558         }\r
559         return 0;\r
560 }\r
561 \r
562 static SQInteger array_map(HSQUIRRELVM v)\r
563 {\r
564         SQObject &o = stack_get(v,1);\r
565         SQInteger size = _array(o)->Size();\r
566         SQObjectPtr ret = SQArray::Create(_ss(v),size);\r
567         if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))\r
568                 return SQ_ERROR;\r
569         v->Push(ret);\r
570         return 1;\r
571 }\r
572 \r
573 static SQInteger array_apply(HSQUIRRELVM v)\r
574 {\r
575         SQObject &o = stack_get(v,1);\r
576         if(SQ_FAILED(__map_array(_array(o),_array(o),v)))\r
577                 return SQ_ERROR;\r
578         return 0;\r
579 }\r
580 \r
581 static SQInteger array_reduce(HSQUIRRELVM v)\r
582 {\r
583         SQObject &o = stack_get(v,1);\r
584         SQArray *a = _array(o);\r
585         SQInteger size = a->Size();\r
586         if(size == 0) {\r
587                 return 0;\r
588         }\r
589         SQObjectPtr res;\r
590         a->Get(0,res);\r
591         if(size > 1) {\r
592                 SQObjectPtr other;\r
593                 for(SQInteger n = 1; n < size; n++) {\r
594                         a->Get(n,other);\r
595                         v->Push(o);\r
596                         v->Push(res);\r
597                         v->Push(other);\r
598                         if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {\r
599                                 return SQ_ERROR;\r
600                         }\r
601                         res = v->GetUp(-1);\r
602                         v->Pop();\r
603                 }\r
604         }\r
605         v->Push(res);\r
606         return 1;\r
607 }\r
608 \r
609 static SQInteger array_filter(HSQUIRRELVM v)\r
610 {\r
611         SQObject &o = stack_get(v,1);\r
612         SQArray *a = _array(o);\r
613         SQObjectPtr ret = SQArray::Create(_ss(v),0);\r
614         SQInteger size = a->Size();\r
615         SQObjectPtr val;\r
616         for(SQInteger n = 0; n < size; n++) {\r
617                 a->Get(n,val);\r
618                 v->Push(o);\r
619                 v->Push(n);\r
620                 v->Push(val);\r
621                 if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {\r
622                         return SQ_ERROR;\r
623                 }\r
624                 if(!SQVM::IsFalse(v->GetUp(-1))) {\r
625                         _array(ret)->Append(val);\r
626                 }\r
627                 v->Pop();\r
628         }\r
629         v->Push(ret);\r
630         return 1;\r
631 }\r
632 \r
633 static SQInteger array_find(HSQUIRRELVM v)\r
634 {\r
635         SQObject &o = stack_get(v,1);\r
636         SQObjectPtr &val = stack_get(v,2);\r
637         SQArray *a = _array(o);\r
638         SQInteger size = a->Size();\r
639         SQObjectPtr temp;\r
640         for(SQInteger n = 0; n < size; n++) {\r
641                 bool res = false;\r
642                 a->Get(n,temp);\r
643                 if(SQVM::IsEqual(temp,val,res) && res) {\r
644                         v->Push(n);\r
645                         return 1;\r
646                 }\r
647         }\r
648         return 0;\r
649 }\r
650 \r
651 \r
652 bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)\r
653 {\r
654         if(func < 0) {\r
655                 if(!v->ObjCmp(a,b,ret)) return false;\r
656         }\r
657         else {\r
658                 SQInteger top = sq_gettop(v);\r
659                 sq_push(v, func);\r
660                 sq_pushroottable(v);\r
661                 v->Push(a);\r
662                 v->Push(b);\r
663                 if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) {\r
664                         if(!sq_isstring( v->_lasterror)) \r
665                                 v->Raise_Error(_SC("compare func failed"));\r
666                         return false;\r
667                 }\r
668                 if(SQ_FAILED(sq_getinteger(v, -1, &ret))) {\r
669                         v->Raise_Error(_SC("numeric value expected as return value of the compare function"));\r
670                         return false;\r
671                 }\r
672                 sq_settop(v, top);\r
673                 return true;\r
674         }\r
675         return true;\r
676 }\r
677 \r
678 bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)\r
679 {\r
680         SQInteger maxChild;\r
681         SQInteger done = 0;\r
682         SQInteger ret;\r
683         SQInteger root2;\r
684         while (((root2 = root * 2) <= bottom) && (!done))\r
685         {\r
686                 if (root2 == bottom) {\r
687                         maxChild = root2;\r
688                 }\r
689                 else {\r
690                         if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))\r
691                                 return false;\r
692                         if (ret > 0) {\r
693                                 maxChild = root2;\r
694                         }\r
695                         else {\r
696                                 maxChild = root2 + 1;\r
697                         }\r
698                 }\r
699 \r
700                 if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))\r
701                         return false;\r
702                 if (ret < 0) {\r
703                         if (root == maxChild) {\r
704                 v->Raise_Error(_SC("inconsistent compare function"));\r
705                 return false; // We'd be swapping ourselve. The compare function is incorrect\r
706             }\r
707 \r
708                         _Swap(arr->_values[root],arr->_values[maxChild]);\r
709                         root = maxChild;\r
710                 }\r
711                 else {\r
712                         done = 1;\r
713                 }\r
714         }\r
715         return true;\r
716 }\r
717 \r
718 bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)\r
719 {\r
720         SQArray *a = _array(arr);\r
721         SQInteger i;\r
722         SQInteger array_size = a->Size();\r
723         for (i = (array_size / 2); i >= 0; i--) {\r
724                 if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;\r
725         }\r
726 \r
727         for (i = array_size-1; i >= 1; i--)\r
728         {\r
729                 _Swap(a->_values[0],a->_values[i]);\r
730                 if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;\r
731         }\r
732         return true;\r
733 }\r
734 \r
735 static SQInteger array_sort(HSQUIRRELVM v)\r
736 {\r
737         SQInteger func = -1;\r
738         SQObjectPtr &o = stack_get(v,1);\r
739         if(_array(o)->Size() > 1) {\r
740                 if(sq_gettop(v) == 2) func = 2;\r
741                 if(!_hsort(v, o, 0, _array(o)->Size()-1, func))\r
742                         return SQ_ERROR;\r
743 \r
744         }\r
745         return 0;\r
746 }\r
747 \r
748 static SQInteger array_slice(HSQUIRRELVM v)\r
749 {\r
750         SQInteger sidx,eidx;\r
751         SQObjectPtr o;\r
752         if(get_slice_params(v,sidx,eidx,o)==-1)return -1;\r
753         SQInteger alen = _array(o)->Size();\r
754         if(sidx < 0)sidx = alen + sidx;\r
755         if(eidx < 0)eidx = alen + eidx;\r
756         if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));\r
757         if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));\r
758         SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);\r
759         SQObjectPtr t;\r
760         SQInteger count=0;\r
761         for(SQInteger i=sidx;i<eidx;i++){\r
762                 _array(o)->Get(i,t);\r
763                 arr->Set(count++,t);\r
764         }\r
765         v->Push(arr);\r
766         return 1;\r
767         \r
768 }\r
769 \r
770 SQRegFunction SQSharedState::_array_default_delegate_funcz[]={\r
771         {_SC("len"),default_delegate_len,1, _SC("a")},\r
772         {_SC("append"),array_append,2, _SC("a")},\r
773         {_SC("extend"),array_extend,2, _SC("aa")},\r
774         {_SC("push"),array_append,2, _SC("a")},\r
775         {_SC("pop"),array_pop,1, _SC("a")},\r
776         {_SC("top"),array_top,1, _SC("a")},\r
777         {_SC("insert"),array_insert,3, _SC("an")},\r
778         {_SC("remove"),array_remove,2, _SC("an")},\r
779         {_SC("resize"),array_resize,-2, _SC("an")},\r
780         {_SC("reverse"),array_reverse,1, _SC("a")},\r
781         {_SC("sort"),array_sort,-1, _SC("ac")},\r
782         {_SC("slice"),array_slice,-1, _SC("ann")},\r
783         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
784         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
785         {_SC("clear"),obj_clear,1, _SC(".")},\r
786         {_SC("map"),array_map,2, _SC("ac")}, \r
787         {_SC("apply"),array_apply,2, _SC("ac")}, \r
788         {_SC("reduce"),array_reduce,2, _SC("ac")}, \r
789         {_SC("filter"),array_filter,2, _SC("ac")},\r
790         {_SC("find"),array_find,2, _SC("a.")},\r
791         {0,0}\r
792 };\r
793 \r
794 //STRING DEFAULT DELEGATE//////////////////////////\r
795 static SQInteger string_slice(HSQUIRRELVM v)\r
796 {\r
797         SQInteger sidx,eidx;\r
798         SQObjectPtr o;\r
799         if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;\r
800         SQInteger slen = _string(o)->_len;\r
801         if(sidx < 0)sidx = slen + sidx;\r
802         if(eidx < 0)eidx = slen + eidx;\r
803         if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));\r
804         if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));\r
805         v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));\r
806         return 1;\r
807 }\r
808 \r
809 static SQInteger string_find(HSQUIRRELVM v)\r
810 {\r
811         SQInteger top,start_idx=0;\r
812         const SQChar *str,*substr,*ret;\r
813         if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){\r
814                 if(top>2)sq_getinteger(v,3,&start_idx);\r
815                 if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){\r
816                         ret=scstrstr(&str[start_idx],substr);\r
817                         if(ret){\r
818                                 sq_pushinteger(v,(SQInteger)(ret-str));\r
819                                 return 1;\r
820                         }\r
821                 }\r
822                 return 0;\r
823         }\r
824         return sq_throwerror(v,_SC("invalid param"));\r
825 }\r
826 \r
827 #define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \\r
828 { \\r
829         SQObject str=stack_get(v,1); \\r
830         SQInteger len=_string(str)->_len; \\r
831         const SQChar *sThis=_stringval(str); \\r
832         SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \\r
833         for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \\r
834         v->Push(SQString::Create(_ss(v),sNew,len)); \\r
835         return 1; \\r
836 }\r
837 \r
838 \r
839 STRING_TOFUNCZ(tolower)\r
840 STRING_TOFUNCZ(toupper)\r
841 \r
842 SQRegFunction SQSharedState::_string_default_delegate_funcz[]={\r
843         {_SC("len"),default_delegate_len,1, _SC("s")},\r
844         {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},\r
845         {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},\r
846         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
847         {_SC("slice"),string_slice,-1, _SC(" s n  n")},\r
848         {_SC("find"),string_find,-2, _SC("s s n ")},\r
849         {_SC("tolower"),string_tolower,1, _SC("s")},\r
850         {_SC("toupper"),string_toupper,1, _SC("s")},\r
851         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
852         {0,0}\r
853 };\r
854 \r
855 //INTEGER DEFAULT DELEGATE//////////////////////////\r
856 SQRegFunction SQSharedState::_number_default_delegate_funcz[]={\r
857         {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},\r
858         {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},\r
859         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
860         {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},\r
861         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
862         {0,0}\r
863 };\r
864 \r
865 //CLOSURE DEFAULT DELEGATE//////////////////////////\r
866 static SQInteger closure_pcall(HSQUIRRELVM v)\r
867 {\r
868         return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;\r
869 }\r
870 \r
871 static SQInteger closure_call(HSQUIRRELVM v)\r
872 {\r
873         return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;\r
874 }\r
875 \r
876 static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)\r
877 {\r
878         SQArray *aparams=_array(stack_get(v,2));\r
879         SQInteger nparams=aparams->Size();\r
880         v->Push(stack_get(v,1));\r
881         for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);\r
882         return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;\r
883 }\r
884 \r
885 static SQInteger closure_acall(HSQUIRRELVM v)\r
886 {\r
887         return _closure_acall(v,SQTrue);\r
888 }\r
889 \r
890 static SQInteger closure_pacall(HSQUIRRELVM v)\r
891 {\r
892         return _closure_acall(v,SQFalse);\r
893 }\r
894 \r
895 static SQInteger closure_bindenv(HSQUIRRELVM v)\r
896 {\r
897         if(SQ_FAILED(sq_bindenv(v,1)))\r
898                 return SQ_ERROR;\r
899         return 1;\r
900 }\r
901 \r
902 static SQInteger closure_getinfos(HSQUIRRELVM v) {\r
903         SQObject o = stack_get(v,1);\r
904         SQTable *res = SQTable::Create(_ss(v),4);\r
905         if(type(o) == OT_CLOSURE) {\r
906                 SQFunctionProto *f = _closure(o)->_function;\r
907                 SQInteger nparams = f->_nparameters + (f->_varparams?1:0);\r
908                 SQObjectPtr params = SQArray::Create(_ss(v),nparams);\r
909     SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams);\r
910                 for(SQInteger n = 0; n<f->_nparameters; n++) {\r
911                         _array(params)->Set((SQInteger)n,f->_parameters[n]);\r
912                 }\r
913     for(SQInteger j = 0; j<f->_ndefaultparams; j++) {\r
914                         _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]);\r
915                 }\r
916                 if(f->_varparams) {\r
917                         _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));\r
918                 }\r
919                 res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false);\r
920                 res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name);\r
921                 res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);\r
922                 res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);\r
923                 res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);\r
924     res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams);\r
925         }\r
926         else { //OT_NATIVECLOSURE \r
927                 SQNativeClosure *nc = _nativeclosure(o);\r
928                 res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);\r
929                 res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);\r
930                 res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);\r
931                 SQObjectPtr typecheck;\r
932                 if(nc->_typecheck.size() > 0) {\r
933                         typecheck =\r
934                                 SQArray::Create(_ss(v), nc->_typecheck.size());\r
935                         for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {\r
936                                         _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);\r
937                         }\r
938                 }\r
939                 res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);\r
940         }\r
941         v->Push(res);\r
942         return 1;\r
943 }\r
944 \r
945 \r
946 \r
947 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
948         {_SC("call"),closure_call,-1, _SC("c")},\r
949         {_SC("pcall"),closure_pcall,-1, _SC("c")},\r
950         {_SC("acall"),closure_acall,2, _SC("ca")},\r
951         {_SC("pacall"),closure_pacall,2, _SC("ca")},\r
952         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
953         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
954         {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},\r
955         {_SC("getinfos"),closure_getinfos,1, _SC("c")},\r
956         {0,0}\r
957 };\r
958 \r
959 //GENERATOR DEFAULT DELEGATE\r
960 static SQInteger generator_getstatus(HSQUIRRELVM v)\r
961 {\r
962         SQObject &o=stack_get(v,1);\r
963         switch(_generator(o)->_state){\r
964                 case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;\r
965                 case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;\r
966                 case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;\r
967         }\r
968         return 1;\r
969 }\r
970 \r
971 SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={\r
972         {_SC("getstatus"),generator_getstatus,1, _SC("g")},\r
973         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
974         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
975         {0,0}\r
976 };\r
977 \r
978 //THREAD DEFAULT DELEGATE\r
979 static SQInteger thread_call(HSQUIRRELVM v)\r
980 {\r
981         SQObjectPtr o = stack_get(v,1);\r
982         if(type(o) == OT_THREAD) {\r
983                 SQInteger nparams = sq_gettop(v);\r
984                 _thread(o)->Push(_thread(o)->_roottable);\r
985                 for(SQInteger i = 2; i<(nparams+1); i++)\r
986                         sq_move(_thread(o),v,i);\r
987                 if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) {\r
988                         sq_move(v,_thread(o),-1);\r
989                         sq_pop(_thread(o),1);\r
990                         return 1;\r
991                 }\r
992                 v->_lasterror = _thread(o)->_lasterror;\r
993                 return SQ_ERROR;\r
994         }\r
995         return sq_throwerror(v,_SC("wrong parameter"));\r
996 }\r
997 \r
998 static SQInteger thread_wakeup(HSQUIRRELVM v)\r
999 {\r
1000         SQObjectPtr o = stack_get(v,1);\r
1001         if(type(o) == OT_THREAD) {\r
1002                 SQVM *thread = _thread(o);\r
1003                 SQInteger state = sq_getvmstate(thread);\r
1004                 if(state != SQ_VMSTATE_SUSPENDED) {\r
1005                         switch(state) {\r
1006                                 case SQ_VMSTATE_IDLE:\r
1007                                         return sq_throwerror(v,_SC("cannot wakeup a idle thread"));\r
1008                                 break;\r
1009                                 case SQ_VMSTATE_RUNNING:\r
1010                                         return sq_throwerror(v,_SC("cannot wakeup a running thread"));\r
1011                                 break;\r
1012                         }\r
1013                 }\r
1014                         \r
1015                 SQInteger wakeupret = sq_gettop(v)>1?1:0;\r
1016                 if(wakeupret) {\r
1017                         sq_move(thread,v,2);\r
1018                 }\r
1019                 if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) {\r
1020                         sq_move(v,thread,-1);\r
1021                         sq_pop(thread,1); //pop retval\r
1022                         if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {\r
1023                                 sq_settop(thread,1); //pop roottable\r
1024                         }\r
1025                         return 1;\r
1026                 }\r
1027                 sq_settop(thread,1);\r
1028                 v->_lasterror = thread->_lasterror;\r
1029                 return SQ_ERROR;\r
1030         }\r
1031         return sq_throwerror(v,_SC("wrong parameter"));\r
1032 }\r
1033 \r
1034 static SQInteger thread_getstatus(HSQUIRRELVM v)\r
1035 {\r
1036         SQObjectPtr &o = stack_get(v,1);\r
1037         switch(sq_getvmstate(_thread(o))) {\r
1038                 case SQ_VMSTATE_IDLE:\r
1039                         sq_pushstring(v,_SC("idle"),-1);\r
1040                 break;\r
1041                 case SQ_VMSTATE_RUNNING:\r
1042                         sq_pushstring(v,_SC("running"),-1);\r
1043                 break;\r
1044                 case SQ_VMSTATE_SUSPENDED:\r
1045                         sq_pushstring(v,_SC("suspended"),-1);\r
1046                 break;\r
1047                 default:\r
1048                         return sq_throwerror(v,_SC("internal VM error"));\r
1049         }\r
1050         return 1;\r
1051 }\r
1052 \r
1053 static SQInteger thread_getstackinfos(HSQUIRRELVM v)\r
1054 {\r
1055         SQObjectPtr o = stack_get(v,1);\r
1056         if(type(o) == OT_THREAD) {\r
1057                 SQVM *thread = _thread(o);\r
1058                 SQInteger threadtop = sq_gettop(thread);\r
1059                 SQInteger level;\r
1060                 sq_getinteger(v,-1,&level);\r
1061                 SQRESULT res = __getcallstackinfos(thread,level);\r
1062                 if(SQ_FAILED(res))\r
1063                 {\r
1064                         sq_settop(thread,threadtop);\r
1065                         if(type(thread->_lasterror) == OT_STRING) {\r
1066                                 sq_throwerror(v,_stringval(thread->_lasterror));\r
1067                         }\r
1068                         else {\r
1069                                 sq_throwerror(v,_SC("unknown error"));\r
1070                         }\r
1071                 }\r
1072                 if(res > 0) {\r
1073                         //some result\r
1074                         sq_move(v,thread,-1);\r
1075                         sq_settop(thread,threadtop);\r
1076                         return 1;\r
1077                 }\r
1078                 //no result\r
1079                 sq_settop(thread,threadtop);\r
1080                 return 0;\r
1081                 \r
1082         }\r
1083         return sq_throwerror(v,_SC("wrong parameter"));\r
1084 }\r
1085 \r
1086 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {\r
1087         {_SC("call"), thread_call, -1, _SC("v")},\r
1088         {_SC("wakeup"), thread_wakeup, -1, _SC("v")},\r
1089         {_SC("getstatus"), thread_getstatus, 1, _SC("v")},\r
1090         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
1091         {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},\r
1092         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
1093         {0,0},\r
1094 };\r
1095 \r
1096 static SQInteger class_getattributes(HSQUIRRELVM v)\r
1097 {\r
1098         return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;\r
1099 }\r
1100 \r
1101 static SQInteger class_setattributes(HSQUIRRELVM v)\r
1102 {\r
1103         return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;\r
1104 }\r
1105 \r
1106 static SQInteger class_instance(HSQUIRRELVM v)\r
1107 {\r
1108         return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;\r
1109 }\r
1110 \r
1111 static SQInteger class_getbase(HSQUIRRELVM v)\r
1112 {\r
1113         return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;\r
1114 }\r
1115 \r
1116 static SQInteger class_newmember(HSQUIRRELVM v)\r
1117 {\r
1118         SQInteger top = sq_gettop(v);\r
1119         SQBool bstatic = SQFalse;\r
1120         if(top == 5)\r
1121         {\r
1122                 sq_tobool(v,-1,&bstatic);\r
1123                 sq_pop(v,1);\r
1124         }\r
1125 \r
1126         if(top < 4) {\r
1127                 sq_pushnull(v);\r
1128         }\r
1129         return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR;\r
1130 }\r
1131 \r
1132 static SQInteger class_rawnewmember(HSQUIRRELVM v)\r
1133 {\r
1134         SQInteger top = sq_gettop(v);\r
1135         SQBool bstatic = SQFalse;\r
1136         if(top == 5)\r
1137         {\r
1138                 sq_tobool(v,-1,&bstatic);\r
1139                 sq_pop(v,1);\r
1140         }\r
1141 \r
1142         if(top < 4) {\r
1143                 sq_pushnull(v);\r
1144         }\r
1145         return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR;\r
1146 }\r
1147 \r
1148 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {\r
1149         {_SC("getattributes"), class_getattributes, 2, _SC("y.")},\r
1150         {_SC("setattributes"), class_setattributes, 3, _SC("y..")},\r
1151         {_SC("rawget"),container_rawget,2, _SC("y")},\r
1152         {_SC("rawset"),container_rawset,3, _SC("y")},\r
1153         {_SC("rawin"),container_rawexists,2, _SC("y")},\r
1154         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
1155         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
1156         {_SC("instance"),class_instance,1, _SC("y")},\r
1157         {_SC("getbase"),class_getbase,1, _SC("y")},\r
1158         {_SC("newmember"),class_newmember,-3, _SC("y")},\r
1159         {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},\r
1160         {0,0}\r
1161 };\r
1162 \r
1163 \r
1164 static SQInteger instance_getclass(HSQUIRRELVM v)\r
1165 {\r
1166         if(SQ_SUCCEEDED(sq_getclass(v,1)))\r
1167                 return 1;\r
1168         return SQ_ERROR;\r
1169 }\r
1170 \r
1171 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {\r
1172         {_SC("getclass"), instance_getclass, 1, _SC("x")},\r
1173         {_SC("rawget"),container_rawget,2, _SC("x")},\r
1174         {_SC("rawset"),container_rawset,3, _SC("x")},\r
1175         {_SC("rawin"),container_rawexists,2, _SC("x")},\r
1176         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
1177         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
1178         {0,0}\r
1179 };\r
1180 \r
1181 static SQInteger weakref_ref(HSQUIRRELVM v)\r
1182 {\r
1183         if(SQ_FAILED(sq_getweakrefval(v,1)))\r
1184                 return SQ_ERROR;\r
1185         return 1;\r
1186 }\r
1187 \r
1188 SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {\r
1189         {_SC("ref"),weakref_ref,1, _SC("r")},\r
1190         {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
1191         {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
1192         {0,0}\r
1193 };\r
1194 \r