Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/tolua/tolua_is.c @ 2926

Last change on this file since 2926 was 2710, checked in by rgrieder, 16 years ago

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

  • Property svn:eol-style set to native
File size: 11.8 KB
Line 
1/* tolua: functions to check types.
2** Support code for Lua bindings.
3** Written by Waldemar Celes
4** TeCGraf/PUC-Rio
5** Apr 2003
6** $Id: $
7*/
8
9/* This code is free software; you can redistribute it and/or modify it.
10** The software provided hereunder is on an "as is" basis, and
11** the author has no obligation to provide maintenance, support, updates,
12** enhancements, or modifications.
13*/
14
15#include "tolua++.h"
16#include "lauxlib.h"
17
18#include <stdlib.h>
19#include <string.h>
20
21/* a fast check if a is b, without parameter validation
22 i.e. if b is equal to a or a superclass of a. */
23TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index)
24{
25 int result;
26        if (lua_rawequal(L,mt_indexa,mt_indexb))
27                result = 1;
28        else
29        {
30                if (super_index) {
31                        lua_pushvalue(L, super_index);
32                } else {
33                        lua_pushliteral(L,"tolua_super");
34                        lua_rawget(L,LUA_REGISTRYINDEX);  /* stack: super */
35                };
36                lua_pushvalue(L,mt_indexa);       /* stack: super mta */
37                lua_rawget(L,-2);                 /* stack: super super[mta] */
38                lua_pushvalue(L,mt_indexb);       /* stack: super super[mta] mtb */
39                lua_rawget(L,LUA_REGISTRYINDEX);  /* stack: super super[mta] typenameB */
40                lua_rawget(L,-2);                 /* stack: super super[mta] bool */
41                result = lua_toboolean(L,-1);
42                lua_pop(L,3);
43        }
44        return result;
45}
46
47/* Push and returns the corresponding object typename */
48TOLUA_API const char* tolua_typename (lua_State* L, int lo)
49{
50        int tag = lua_type(L,lo);
51 if (tag == LUA_TNONE)
52  lua_pushstring(L,"[no object]");
53 else if (tag != LUA_TUSERDATA && tag != LUA_TTABLE)
54  lua_pushstring(L,lua_typename(L,tag));
55 else if (tag == LUA_TUSERDATA)
56 {
57  if (!lua_getmetatable(L,lo))
58   lua_pushstring(L,lua_typename(L,tag));
59                else
60                {
61                 lua_rawget(L,LUA_REGISTRYINDEX);
62                 if (!lua_isstring(L,-1))
63                        {
64                  lua_pop(L,1);
65                                lua_pushstring(L,"[undefined]");
66                        }
67                }
68        }
69        else  /* is table */
70        {
71                lua_pushvalue(L,lo);
72                lua_rawget(L,LUA_REGISTRYINDEX);
73                if (!lua_isstring(L,-1))
74                {
75                        lua_pop(L,1);
76                        lua_pushstring(L,"table");
77                }
78                else
79                {
80   lua_pushstring(L,"class ");
81                        lua_insert(L,-2);
82                        lua_concat(L,2);
83                }
84        }
85        return lua_tostring(L,-1);
86}
87
88TOLUA_API void tolua_error (lua_State* L, char* msg, tolua_Error* err)
89{
90        if (msg[0] == '#')
91        {
92  const char* expected = err->type;
93                const char* provided = tolua_typename(L,err->index);
94  if (msg[1]=='f')
95  {
96   int narg = err->index;
97                        if (err->array)
98    luaL_error(L,"%s\n     argument #%d is array of '%s'; array of '%s' expected.\n",
99               msg+2,narg,provided,expected);
100                        else
101    luaL_error(L,"%s\n     argument #%d is '%s'; '%s' expected.\n",
102               msg+2,narg,provided,expected);
103  }
104  else if (msg[1]=='v')
105                {
106                        if (err->array)
107    luaL_error(L,"%s\n     value is array of '%s'; array of '%s' expected.\n",
108               msg+2,provided,expected);
109                        else
110    luaL_error(L,"%s\n     value is '%s'; '%s' expected.\n",
111               msg+2,provided,expected);
112                }
113 }
114 else
115  luaL_error(L,msg);
116}
117
118/* the equivalent of lua_is* for usertable */
119static  int lua_isusertable (lua_State* L, int lo, const char* type)
120{
121        int r = 0;
122        if (lo < 0) lo = lua_gettop(L)+lo+1;
123        lua_pushvalue(L,lo);
124        lua_rawget(L,LUA_REGISTRYINDEX);  /* get registry[t] */
125        if (lua_isstring(L,-1))
126        {
127                r = strcmp(lua_tostring(L,-1),type)==0;
128                if (!r)
129                {
130                        /* try const */
131                        lua_pushstring(L,"const ");
132                        lua_insert(L,-2);
133                        lua_concat(L,2);
134                        r = lua_isstring(L,-1) && strcmp(lua_tostring(L,-1),type)==0;
135                }
136        }
137        lua_pop(L, 1);
138        return r;
139}
140
141int push_table_instance(lua_State* L, int lo) {
142
143        if (lua_istable(L, lo)) {
144
145                lua_pushstring(L, ".c_instance");
146                lua_gettable(L, lo);
147                if (lua_isuserdata(L, -1)) {
148
149                        lua_replace(L, lo);
150                        return 1;
151                } else {
152
153                        lua_pop(L, 1);
154                        return 0;
155                };
156        } else {
157                return 0;
158        };
159
160        return 0;
161};
162
163/* the equivalent of lua_is* for usertype */
164static int lua_isusertype (lua_State* L, int lo, const char* type)
165{
166        if (!lua_isuserdata(L,lo)) {
167                if (!push_table_instance(L, lo)) {
168                        return 0;
169                };
170        };
171        {
172                /* check if it is of the same type */
173                int r;
174                const char *tn;
175                if (lua_getmetatable(L,lo))        /* if metatable? */
176                {
177                 lua_rawget(L,LUA_REGISTRYINDEX);  /* get registry[mt] */
178                 tn = lua_tostring(L,-1);
179                 r = tn && (strcmp(tn,type) == 0);
180                 lua_pop(L, 1);
181                        if (r)
182                         return 1;
183                        else
184                        {
185                                /* check if it is a specialized class */
186                                lua_pushstring(L,"tolua_super");
187                                lua_rawget(L,LUA_REGISTRYINDEX); /* get super */
188                                lua_getmetatable(L,lo);
189                                lua_rawget(L,-2);                /* get super[mt] */
190                                if (lua_istable(L,-1))
191                                {
192                                        int b;
193                                        lua_pushstring(L,type);
194                                        lua_rawget(L,-2);                /* get super[mt][type] */
195                                        b = lua_toboolean(L,-1);
196                                        lua_pop(L,3);
197                                        if (b)
198                                         return 1;
199                                }
200                        }
201                }
202 }
203        return 0;
204}
205
206TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err)
207{
208 if (lua_gettop(L)<abs(lo))
209                return 1;
210        err->index = lo;
211        err->array = 0;
212        err->type = "[no object]";
213 return 0;
214}
215TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err)
216{
217        if (def || abs(lo)<=lua_gettop(L))  /* any valid index */
218                return 1;
219        err->index = lo;
220        err->array = 0;
221        err->type = "value";
222        return 0;
223}
224
225TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err)
226{
227        if (def && lua_gettop(L)<abs(lo))
228                return 1;
229        if (lua_isnil(L,lo) || lua_isboolean(L,lo))
230                return 1;
231        err->index = lo;
232        err->array = 0;
233        err->type = "boolean";
234        return 0;
235}
236
237TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err)
238{
239        if (def && lua_gettop(L)<abs(lo))
240                return 1;
241        if (lua_isnumber(L,lo))
242                return 1;
243        err->index = lo;
244        err->array = 0;
245        err->type = "number";
246        return 0;
247}
248
249TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err)
250{
251        if (def && lua_gettop(L)<abs(lo))
252                return 1;
253 if (lua_isnil(L,lo) || lua_isstring(L,lo))
254                return 1;
255        err->index = lo;
256        err->array = 0;
257        err->type = "string";
258        return 0;
259}
260
261TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err)
262{
263        if (def && lua_gettop(L)<abs(lo))
264                return 1;
265        if (lua_istable(L,lo))
266                return 1;
267        err->index = lo;
268        err->array = 0;
269        err->type = "table";
270        return 0;
271}
272
273TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
274{
275        if (def && lua_gettop(L)<abs(lo))
276                return 1;
277        if (lua_isusertable(L,lo,type))
278                return 1;
279        err->index = lo;
280        err->array = 0;
281        err->type = type;
282        return 0;
283}
284
285
286TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err)
287{
288        if (def && lua_gettop(L)<abs(lo))
289                return 1;
290        if (lua_isnil(L,lo) || lua_isuserdata(L,lo))
291                return 1;
292        err->index = lo;
293        err->array = 0;
294        err->type = "userdata";
295        return 0;
296}
297
298TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
299{
300        if (def && lua_gettop(L)<abs(lo))
301                return 1;
302        if (lua_isnil(L,lo) || lua_isusertype(L,lo,type))
303                return 1;
304        err->index = lo;
305        err->array = 0;
306        err->type = type;
307        return 0;
308}
309
310TOLUA_API int tolua_isvaluearray
311 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
312{
313        if (!tolua_istable(L,lo,def,err))
314                return 0;
315        else
316                return 1;
317}
318
319TOLUA_API int tolua_isbooleanarray
320 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
321{
322        if (!tolua_istable(L,lo,def,err))
323                return 0;
324        else
325        {
326                int i;
327                for (i=1; i<=dim; ++i)
328                {
329                        lua_pushnumber(L,i);
330                        lua_gettable(L,lo);
331          if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
332                                          !(def && lua_isnil(L,-1))
333                                                )
334                        {
335                                err->index = lo;
336                                err->array = 1;
337                                err->type = "boolean";
338                                return 0;
339                        }
340                        lua_pop(L,1);
341                }
342 }
343 return 1;
344}
345
346TOLUA_API int tolua_isnumberarray
347 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
348{
349        if (!tolua_istable(L,lo,def,err))
350                return 0;
351        else
352        {
353                int i;
354                for (i=1; i<=dim; ++i)
355                {
356                        lua_pushnumber(L,i);
357                        lua_gettable(L,lo);
358                        if (!lua_isnumber(L,-1) &&
359                                          !(def && lua_isnil(L,-1))
360                                                )
361                        {
362                                err->index = lo;
363                                err->array = 1;
364                                err->type = "number";
365                                return 0;
366                        }
367                        lua_pop(L,1);
368                }
369 }
370 return 1;
371}
372
373TOLUA_API int tolua_isstringarray
374 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
375{
376        if (!tolua_istable(L,lo,def,err))
377                return 0;
378        else
379        {
380                int i;
381                for (i=1; i<=dim; ++i)
382                {
383                        lua_pushnumber(L,i);
384                        lua_gettable(L,lo);
385   if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
386                            !(def && lua_isnil(L,-1))
387                                                )
388                        {
389                                err->index = lo;
390                                err->array = 1;
391                                err->type = "string";
392                                return 0;
393                        }
394                        lua_pop(L,1);
395                }
396 }
397 return 1;
398}
399
400TOLUA_API int tolua_istablearray
401 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
402{
403        if (!tolua_istable(L,lo,def,err))
404                return 0;
405        else
406        {
407                int i;
408                for (i=1; i<=dim; ++i)
409                {
410                        lua_pushnumber(L,i);
411                        lua_gettable(L,lo);
412          if (! lua_istable(L,-1) &&
413                            !(def && lua_isnil(L,-1))
414                                                )
415                        {
416                                err->index = lo;
417                                err->array = 1;
418                                err->type = "table";
419                                return 0;
420                        }
421                        lua_pop(L,1);
422                }
423 }
424 return 1;
425}
426
427TOLUA_API int tolua_isuserdataarray
428 (lua_State* L, int lo, int dim, int def, tolua_Error* err)
429{
430        if (!tolua_istable(L,lo,def,err))
431                return 0;
432        else
433        {
434                int i;
435                for (i=1; i<=dim; ++i)
436                {
437                        lua_pushnumber(L,i);
438                        lua_gettable(L,lo);
439          if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
440                            !(def && lua_isnil(L,-1))
441                                                )
442                        {
443                                err->index = lo;
444                                err->array = 1;
445                                err->type = "userdata";
446                                return 0;
447                        }
448                        lua_pop(L,1);
449                }
450 }
451 return 1;
452}
453
454TOLUA_API int tolua_isusertypearray
455 (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err)
456{
457        if (!tolua_istable(L,lo,def,err))
458                return 0;
459        else
460        {
461                int i;
462                for (i=1; i<=dim; ++i)
463                {
464                        lua_pushnumber(L,i);
465                        lua_gettable(L,lo);
466          if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
467                            !(def && lua_isnil(L,-1))
468                                                )
469                        {
470                                err->index = lo;
471                                err->type = type;
472                                err->array = 1;
473                                return 0;
474                        }
475                        lua_pop(L,1);
476                }
477 }
478 return 1;
479}
480
481#if 0
482int tolua_isbooleanfield
483 (lua_State* L, int lo, int i, int def, tolua_Error* err)
484{
485        lua_pushnumber(L,i);
486        lua_gettable(L,lo);
487        if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
488                          !(def && lua_isnil(L,-1))
489                                )
490        {
491                err->index = lo;
492                err->array = 1;
493                err->type = "boolean";
494                return 0;
495        }
496        lua_pop(L,1);
497 return 1;
498}
499
500int tolua_isnumberfield
501 (lua_State* L, int lo, int i, int def, tolua_Error* err)
502{
503        lua_pushnumber(L,i);
504        lua_gettable(L,lo);
505        if (!lua_isnumber(L,-1) &&
506                          !(def && lua_isnil(L,-1))
507                                )
508        {
509                err->index = lo;
510                err->array = 1;
511                err->type = "number";
512                return 0;
513        }
514        lua_pop(L,1);
515 return 1;
516}
517
518int tolua_isstringfield
519 (lua_State* L, int lo, int i, int def, tolua_Error* err)
520{
521        lua_pushnumber(L,i);
522        lua_gettable(L,lo);
523 if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
524            !(def && lua_isnil(L,-1))
525                                )
526        {
527                err->index = lo;
528                err->array = 1;
529                err->type = "string";
530                return 0;
531        }
532        lua_pop(L,1);
533 return 1;
534}
535
536int tolua_istablefield
537 (lua_State* L, int lo, int i, int def, tolua_Error* err)
538{
539        lua_pushnumber(L,i+1);
540        lua_gettable(L,lo);
541        if (! lua_istable(L,-1) &&
542            !(def && lua_isnil(L,-1))
543                                )
544        {
545                err->index = lo;
546                err->array = 1;
547                err->type = "table";
548                return 0;
549        }
550        lua_pop(L,1);
551}
552
553int tolua_isusertablefield
554 (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
555{
556        lua_pushnumber(L,i);
557        lua_gettable(L,lo);
558        if (! lua_isusertable(L,-1,type) &&
559            !(def && lua_isnil(L,-1))
560                                )
561        {
562                err->index = lo;
563                err->array = 1;
564                err->type = type;
565                return 0;
566        }
567        lua_pop(L,1);
568 return 1;
569}
570
571int tolua_isuserdatafield
572 (lua_State* L, int lo, int i, int def, tolua_Error* err)
573{
574        lua_pushnumber(L,i);
575        lua_gettable(L,lo);
576        if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
577            !(def && lua_isnil(L,-1))
578                                )
579        {
580                err->index = lo;
581                err->array = 1;
582                err->type = "userdata";
583                return 0;
584        }
585        lua_pop(L,1);
586 return 1;
587}
588
589int tolua_isusertypefield
590 (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
591{
592        lua_pushnumber(L,i);
593        lua_gettable(L,lo);
594        if (!(lua_isnil(L,-1) || lua_isusertype(L,-1,type)) &&
595            !(def && lua_isnil(L,-1))
596                                )
597        {
598                err->index = lo;
599                err->type = type;
600                err->array = 1;
601                return 0;
602        }
603        lua_pop(L,1);
604 return 1;
605}
606
607#endif
Note: See TracBrowser for help on using the repository browser.