util.c
author Myhailo Danylenko <isbear@ukrpost.net>
Sun, 01 Feb 2009 21:28:57 +0200
changeset 0 84fdfb0344c9
child 4 5770be2d5f3f
permissions -rw-r--r--
Initial commit * It works * Still need to debug objects collection


#include <glib.h>	// g_ascii_strcasecmp
#include <lua.h>
#include <lauxlib.h>

#include "util.h"

enum_value_t string2enum (const char *string, const string2enum_t *set)
{
	while (set->string) {
		if (!g_ascii_strcasecmp (string, set->string))
			return set->value;
		++set;
	}
	return set->value;
}

const char *enum2string (enum_value_t value, const string2enum_t *set)
{
	while (set->string) {
		if (value == set->value)
			return set->string;
		++set;
	}
	return NULL;
}

enum_value_t luaL_checkenum (lua_State *L, int index, const string2enum_t *set)
{
	if (lua_type (L, index) == LUA_TNUMBER)
		return lua_tointeger (L, index);
	else
		return string2enum (luaL_checkstring (L, index), set);
}

void luaL_pushenum (lua_State *L, enum_value_t value, const string2enum_t *set)
{
	const char *string = enum2string (value, set);
	if (string != NULL)
		lua_pushstring (L, string);
	else
		lua_pushinteger (L, value);
}

enum_value_t luaL_checkenum_multi (lua_State *L, int index, const string2enum_t *set)
{
	int type = lua_type (L, index);
	if (type == LUA_TNUMBER)
		return lua_tointeger (L, index);
	else if (type == LUA_TSTRING)
		return string2enum (lua_tostring (L, index), set);
	else if (type == LUA_TTABLE) {
		enum_value_t retval = 0;
		lua_pushnil (L);
		while (lua_next (L, index) != 0) {
			type = lua_type (L, -2);
			if (type == LUA_TNUMBER) {
				type = lua_type (L, -1);
				if (type == LUA_TNUMBER)
					retval |= lua_tointeger (L, -1);
				else if (type == LUA_TSTRING)
					retval |= string2enum (lua_tostring (L, -1), set);
				else
					luaL_argerror (L, index, "wrong value type of flag");
			} else if (type == LUA_TSTRING) {
				if (lua_toboolean (L, -1))
					retval |= string2enum (lua_tostring (L, -2), set);
			} else
				luaL_argerror (L, index, "wrong key type of flags table");
			lua_pop (L, 1);
		}
	} else
		luaL_argerror (L, index, "integer, string, or table of ones expected");
	return 0; // never happens
}

void luaL_pushenum_multi (lua_State *L, enum_value_t value, const string2enum_t *set)
{
	enum_value_t matched = 0;
	lua_newtable (L);
	while (set->string) {
		if (value & set->value) {
			matched |= set->value & value;
			lua_pushstring (L, set->string);
			lua_pushboolean (L, 1);
			lua_settable (L, -3);
		}
		++set;
	}
	if (value ^ matched) {
		lua_pushinteger (L, 1);
		lua_pushinteger (L, value ^ matched);
		lua_settable (L, -3);
	}
}

void *luaL_malloc (lua_State *L, size_t size)
{
	void      *ud;
	lua_Alloc  allocf = lua_getallocf (L, &ud);
	return (*allocf) (ud, NULL, 0, size);
}

void *luaL_realloc (lua_State *L, void *ptr, size_t osize, size_t nsize)
{
	void      *ud;
	lua_Alloc  allocf = lua_getallocf (L, &ud);
	return (*allocf) (ud, ptr, osize, nsize);
}

void  luaL_free (lua_State *L, void *ptr)
{
	void      *ud;
	lua_Alloc  allocf = lua_getallocf (L, &ud);
	(*allocf) (ud, ptr, 1, 0);
}