isbear@23: isbear@23: /* Copyright 2009 Myhailo Danylenko isbear@23: isbear@23: This code is free software: you can redistribute it and/or modify isbear@23: it under the terms of the GNU General Public License as published by isbear@23: the Free Software Foundation, either version 2 of the License, or isbear@23: (at your option) any later version. isbear@23: isbear@23: This program is distributed in the hope that it will be useful, isbear@23: but WITHOUT ANY WARRANTY; without even the implied warranty of isbear@23: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the isbear@23: GNU General Public License for more details. isbear@23: isbear@23: You should have received a copy of the GNU General Public License isbear@23: along with this program. If not, see . */ isbear@0: isbear@20: #include isbear@0: #include isbear@0: #include isbear@0: isbear@0: #include "util.h" isbear@0: isbear@50: /// Utility Lua Routines isbear@50: /// To handle conversion of enums and flag fields to/from human-readable strings. isbear@50: isbear@0: enum_value_t string2enum (const char *string, const string2enum_t *set) isbear@0: { isbear@0: while (set->string) { isbear@20: if (!strcasecmp (string, set->string)) isbear@0: return set->value; isbear@0: ++set; isbear@0: } isbear@0: return set->value; isbear@0: } isbear@0: isbear@0: const char *enum2string (enum_value_t value, const string2enum_t *set) isbear@0: { isbear@0: while (set->string) { isbear@0: if (value == set->value) isbear@0: return set->string; isbear@0: ++set; isbear@0: } isbear@0: return NULL; isbear@0: } isbear@0: isbear@4: /// argument enum field isbear@4: /// String that will be converted to number or just plain number, that will be passed as is. isbear@4: /// Note, that if enum name is not recognized no error will be raised and default vale will be used. isbear@0: enum_value_t luaL_checkenum (lua_State *L, int index, const string2enum_t *set) isbear@0: { isbear@0: if (lua_type (L, index) == LUA_TNUMBER) isbear@0: return lua_tointeger (L, index); isbear@0: else isbear@0: return string2enum (luaL_checkstring (L, index), set); isbear@0: } isbear@0: isbear@4: /// return enum field isbear@4: /// String. If no string found, plain number will be returned. isbear@0: void luaL_pushenum (lua_State *L, enum_value_t value, const string2enum_t *set) isbear@0: { isbear@0: const char *string = enum2string (value, set); isbear@0: if (string != NULL) isbear@0: lua_pushstring (L, string); isbear@0: else isbear@0: lua_pushinteger (L, value); isbear@0: } isbear@0: isbear@4: /// argument flags field isbear@4: /// Can be just plain number, then it is passed as is. isbear@4: /// Can be a string, then it is recognized as a single enabled flag. isbear@4: /// Or can be a table of the following format: isbear@4: /// * integer keys should have string values, that will be used as enabled flag names or numerical values, that will be just ORed; isbear@4: /// * string keys should be flag names, that will be enabled, if corresponding value contains true value. isbear@0: enum_value_t luaL_checkenum_multi (lua_State *L, int index, const string2enum_t *set) isbear@0: { isbear@0: int type = lua_type (L, index); isbear@0: if (type == LUA_TNUMBER) isbear@0: return lua_tointeger (L, index); isbear@0: else if (type == LUA_TSTRING) isbear@0: return string2enum (lua_tostring (L, index), set); isbear@0: else if (type == LUA_TTABLE) { isbear@0: enum_value_t retval = 0; isbear@0: lua_pushnil (L); isbear@0: while (lua_next (L, index) != 0) { isbear@0: type = lua_type (L, -2); isbear@0: if (type == LUA_TNUMBER) { isbear@0: type = lua_type (L, -1); isbear@0: if (type == LUA_TNUMBER) isbear@0: retval |= lua_tointeger (L, -1); isbear@0: else if (type == LUA_TSTRING) isbear@0: retval |= string2enum (lua_tostring (L, -1), set); isbear@0: else isbear@0: luaL_argerror (L, index, "wrong value type of flag"); isbear@0: } else if (type == LUA_TSTRING) { isbear@0: if (lua_toboolean (L, -1)) isbear@0: retval |= string2enum (lua_tostring (L, -2), set); isbear@0: } else isbear@0: luaL_argerror (L, index, "wrong key type of flags table"); isbear@0: lua_pop (L, 1); isbear@0: } isbear@25: return retval; isbear@0: } else isbear@0: luaL_argerror (L, index, "integer, string, or table of ones expected"); isbear@0: return 0; // never happens isbear@0: } isbear@0: isbear@4: /// returned flags field isbear@4: /// Is always a table with present flag names as keys with true values. isbear@4: /// Not present flags are not present in table either. isbear@4: /// Not recognized values, if present, will be stored as a number in a first sequential table member (table[1]). isbear@0: void luaL_pushenum_multi (lua_State *L, enum_value_t value, const string2enum_t *set) isbear@0: { isbear@0: enum_value_t matched = 0; isbear@0: lua_newtable (L); isbear@0: while (set->string) { isbear@0: if (value & set->value) { isbear@0: matched |= set->value & value; isbear@0: lua_pushstring (L, set->string); isbear@0: lua_pushboolean (L, 1); isbear@0: lua_settable (L, -3); isbear@0: } isbear@0: ++set; isbear@0: } isbear@0: if (value ^ matched) { isbear@0: lua_pushinteger (L, 1); isbear@0: lua_pushinteger (L, value ^ matched); isbear@0: lua_settable (L, -3); isbear@0: } isbear@0: } isbear@0: isbear@0: void *luaL_malloc (lua_State *L, size_t size) isbear@0: { isbear@0: void *ud; isbear@0: lua_Alloc allocf = lua_getallocf (L, &ud); isbear@0: return (*allocf) (ud, NULL, 0, size); isbear@0: } isbear@0: isbear@0: void *luaL_realloc (lua_State *L, void *ptr, size_t osize, size_t nsize) isbear@0: { isbear@0: void *ud; isbear@0: lua_Alloc allocf = lua_getallocf (L, &ud); isbear@0: return (*allocf) (ud, ptr, osize, nsize); isbear@0: } isbear@0: isbear@0: void luaL_free (lua_State *L, void *ptr) isbear@0: { isbear@0: void *ud; isbear@0: lua_Alloc allocf = lua_getallocf (L, &ud); isbear@0: (*allocf) (ud, ptr, 1, 0); isbear@0: } isbear@0: