Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2271 was 1810, checked in by rgrieder, 16 years ago

merged ceguilua branch back to trunk

  • 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 "lua/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.