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: