src/lua_func.c
branchnew-lib-errors
changeset 219 cefec18b8268
parent 218 5229a5d098b2
equal deleted inserted replaced
218:5229a5d098b2 219:cefec18b8268
     1 #include "lua_func.h"
       
     2 #include "error.h"
       
     3 
       
     4 #include <lua5.1/lauxlib.h>
       
     5 
       
     6 /**
       
     7  * Pushes onto the stack the value at t[i]
       
     8  */
       
     9 static void lua_getindex (lua_State *L, int t, int i)
       
    10 {
       
    11     lua_pushinteger(L, i);
       
    12     lua_gettable(L, t);
       
    13 }
       
    14 
       
    15 /**
       
    16  * Pushes onto the stack either:
       
    17  *  * the value at t[name]
       
    18  *  * the value at t[index]
       
    19  *
       
    20  *  Returns the new index, or 0, if neither could be found
       
    21  */
       
    22 static int lua_arg_lookup (lua_State *L, int t, const char *name, int index)
       
    23 {
       
    24     // try name
       
    25     lua_getfield(L, t, name);
       
    26 
       
    27     if (!lua_isnil(L, -1))
       
    28         return lua_gettop(L);
       
    29     else
       
    30         lua_pop(L, 1);
       
    31     
       
    32     // try index
       
    33     lua_getindex(L, t, index);
       
    34     
       
    35     if (!lua_isnil(L, -1))
       
    36         return lua_gettop(L);
       
    37 
       
    38     else
       
    39         lua_pop(L, 1);
       
    40     
       
    41     // not found
       
    42     return 0;
       
    43 }
       
    44 
       
    45 static const char *_lua_arg_string (lua_State *L, int index, const char *name, const char *def)
       
    46 {
       
    47     const char *value;
       
    48 
       
    49     // use default?
       
    50     if (lua_isnoneornil(L, index) && def != (const char *) LUA_ARG_REQUIRED)
       
    51         return def;
       
    52     
       
    53     // value given?
       
    54     if ((value = lua_tostring(L, index)))
       
    55         return value;
       
    56    
       
    57     // error
       
    58     luaL_error(L, "missing value for required string argument <%d:%s>", index, name); return NULL;
       
    59 }
       
    60 
       
    61 static bool _lua_arg_bool (lua_State *L, int index, const char *name, int def)
       
    62 {
       
    63     (void) name;
       
    64 
       
    65     // use default?
       
    66     if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED)
       
    67         return def;
       
    68    
       
    69     // value given
       
    70     return lua_toboolean(L, index);
       
    71 }
       
    72 
       
    73 static long _lua_arg_int (lua_State *L, int index, const char *name, long def)
       
    74 {
       
    75     (void) name;
       
    76 
       
    77     // use default?
       
    78     if (lua_isnoneornil(L, index) && def != LUA_ARG_REQUIRED)
       
    79         return def;
       
    80    
       
    81     // conver to integer
       
    82     // XXX: check compatibility?
       
    83     return lua_tointeger(L, index);
       
    84 }
       
    85 
       
    86 static void * _lua_arg_obj (lua_State *L, int index, const struct lua_type *type, bool optional)
       
    87 {
       
    88     // not given?
       
    89     if (!lua_isnoneornil(L, index))
       
    90         return lua_type_get(L, type, index);
       
    91 
       
    92     if (optional)
       
    93         return NULL;
       
    94     
       
    95     luaL_error(L, "missing value for required object argument <%d:%s>", index, type->name);
       
    96     return NULL;
       
    97 }
       
    98 
       
    99 /**
       
   100  * Look up the arg index to use for the given index/name.
       
   101  *
       
   102  * If no value is found for the corresponding index, returns zero.
       
   103  */
       
   104 static int lua_arg_index (lua_State *L, int nargs, int index, const char *name)
       
   105 {
       
   106     // lookup from table?
       
   107     if (nargs == 2 && lua_istable(L, 2) && name) {
       
   108         // push the value from the named field onto the stack
       
   109         lua_getfield(L, 2, name);
       
   110         
       
   111         // no named field?
       
   112         if (lua_isnil(L, -1)) {
       
   113             lua_pop(L, 1);
       
   114 
       
   115             lua_getindex(L, 2, index - 1);
       
   116         }
       
   117 
       
   118         // no index field?
       
   119         if (lua_isnil(L, -1)) {
       
   120             lua_pop(L, 1);
       
   121 
       
   122             return 0;
       
   123         }
       
   124         
       
   125         // found either a named or indexed arg
       
   126         return lua_gettop(L);
       
   127 
       
   128     } else if (index <= nargs) {
       
   129         // use the same index
       
   130         return index;
       
   131 
       
   132     } else {
       
   133         // no index
       
   134         return 0;
       
   135     }
       
   136 }
       
   137 
       
   138 const char *lua_arg_string (lua_State *L, int nargs, int index, const char *name, const char *def)
       
   139 {
       
   140     return _lua_arg_string(L, lua_arg_index(L, nargs, index, name), name, def);
       
   141 }
       
   142 
       
   143 bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def)
       
   144 {
       
   145     return _lua_arg_bool(L, lua_arg_index(L, nargs, index, name), name, def);    
       
   146 }
       
   147 
       
   148 void* lua_arg_obj (lua_State *L, int nargs, int index, const struct lua_type *type, bool optional)
       
   149 {
       
   150     return _lua_arg_obj(L, lua_arg_index(L, nargs, index, NULL), type, optional);
       
   151 }
       
   152 
       
   153 long lua_arg_int (lua_State *L, int nargs, int index, const char *name, long def)
       
   154 {
       
   155     return _lua_arg_int(L, lua_arg_index(L, nargs, index, name), name, def);
       
   156 }
       
   157 
       
   158 void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...)
       
   159 {
       
   160     int argidx = 1, argtbl = 0, idx;
       
   161     const struct lua_func_arg *arg;
       
   162     va_list vargs;
       
   163 
       
   164     // first, the obj argument
       
   165     if (func->type)
       
   166         *obj_ptr = lua_type_get(L, func->type, argidx++);
       
   167 
       
   168     // were we given a table of arguments?
       
   169     if (lua_istable(L, argidx))
       
   170         argtbl = argidx++;
       
   171 
       
   172     // parse the args
       
   173     va_start(vargs, obj_ptr);
       
   174 
       
   175     for (arg = func->args, idx = 1; arg->name && arg->type; arg++, idx++) {
       
   176         int index;
       
   177 
       
   178         // map index
       
   179         if (!argtbl)
       
   180             // direct
       
   181             index = argidx++;
       
   182         
       
   183         else
       
   184             // lookup from table
       
   185             index = lua_arg_lookup(L, argtbl, arg->name, idx);
       
   186         
       
   187         // apply
       
   188         switch (arg->type) {
       
   189             case LUA_ARG_STRING:
       
   190                 *va_arg(vargs, const char **) = _lua_arg_string(L, index, arg->name, arg->def.string);
       
   191                 break;
       
   192 
       
   193             case LUA_ARG_BOOL:
       
   194                 *va_arg(vargs, bool *) = _lua_arg_bool(L, index, arg->name, arg->def.boolean);
       
   195                 break;
       
   196             
       
   197             case LUA_ARG_INT:
       
   198                 *va_arg(vargs, long *) = _lua_arg_int(L, index, arg->name, arg->def.integer);
       
   199                 break;
       
   200 
       
   201             default:
       
   202                 NOT_REACHED();
       
   203         };
       
   204     }
       
   205 
       
   206     va_end(vargs);
       
   207 }