util.c
changeset 0 65cbecad22b4
child 72 d049c92d0809
equal deleted inserted replaced
-1:000000000000 0:65cbecad22b4
       
     1 
       
     2 #include <glib.h>	// g_ascii_strcasecmp
       
     3 #include <lua.h>
       
     4 #include <lauxlib.h>
       
     5 
       
     6 #include "util.h"
       
     7 
       
     8 enum_value_t string2enum (const char *string, const string2enum_t *set)
       
     9 {
       
    10 	while (set->string) {
       
    11 		if (!g_ascii_strcasecmp (string, set->string))
       
    12 			return set->value;
       
    13 		++set;
       
    14 	}
       
    15 	return set->value;
       
    16 }
       
    17 
       
    18 const char *enum2string (enum_value_t value, const string2enum_t *set)
       
    19 {
       
    20 	while (set->string) {
       
    21 		if (value == set->value)
       
    22 			return set->string;
       
    23 		++set;
       
    24 	}
       
    25 	return NULL;
       
    26 }
       
    27 
       
    28 /// argument enum field
       
    29 /// String that will be converted to number or just plain number, that will be passed as is.
       
    30 /// Note, that if enum name is not recognized no error will be raised and default vale will be used.
       
    31 enum_value_t luaL_checkenum (lua_State *L, int index, const string2enum_t *set)
       
    32 {
       
    33 	if (lua_type (L, index) == LUA_TNUMBER)
       
    34 		return lua_tointeger (L, index);
       
    35 	else
       
    36 		return string2enum (luaL_checkstring (L, index), set);
       
    37 }
       
    38 
       
    39 /// return enum field
       
    40 /// String. If no string found, plain number will be returned.
       
    41 void luaL_pushenum (lua_State *L, enum_value_t value, const string2enum_t *set)
       
    42 {
       
    43 	const char *string = enum2string (value, set);
       
    44 	if (string != NULL)
       
    45 		lua_pushstring (L, string);
       
    46 	else
       
    47 		lua_pushinteger (L, value);
       
    48 }
       
    49 
       
    50 /// argument flags field
       
    51 /// Can be just plain number, then it is passed as is.
       
    52 /// Can be a string, then it is recognized as a single enabled flag.
       
    53 /// Or can be a table of the following format:
       
    54 /// * integer keys should have string values, that will be used as enabled flag names or numerical values, that will be just ORed;
       
    55 /// * string keys should be flag names, that will be enabled, if corresponding value contains true value.
       
    56 enum_value_t luaL_checkenum_multi (lua_State *L, int index, const string2enum_t *set)
       
    57 {
       
    58 	int type = lua_type (L, index);
       
    59 	if (type == LUA_TNUMBER)
       
    60 		return lua_tointeger (L, index);
       
    61 	else if (type == LUA_TSTRING)
       
    62 		return string2enum (lua_tostring (L, index), set);
       
    63 	else if (type == LUA_TTABLE) {
       
    64 		enum_value_t retval = 0;
       
    65 		lua_pushnil (L);
       
    66 		while (lua_next (L, index) != 0) {
       
    67 			type = lua_type (L, -2);
       
    68 			if (type == LUA_TNUMBER) {
       
    69 				type = lua_type (L, -1);
       
    70 				if (type == LUA_TNUMBER)
       
    71 					retval |= lua_tointeger (L, -1);
       
    72 				else if (type == LUA_TSTRING)
       
    73 					retval |= string2enum (lua_tostring (L, -1), set);
       
    74 				else
       
    75 					luaL_argerror (L, index, "wrong value type of flag");
       
    76 			} else if (type == LUA_TSTRING) {
       
    77 				if (lua_toboolean (L, -1))
       
    78 					retval |= string2enum (lua_tostring (L, -2), set);
       
    79 			} else
       
    80 				luaL_argerror (L, index, "wrong key type of flags table");
       
    81 			lua_pop (L, 1);
       
    82 		}
       
    83 	} else
       
    84 		luaL_argerror (L, index, "integer, string, or table of ones expected");
       
    85 	return 0; // never happens
       
    86 }
       
    87 
       
    88 /// returned flags field
       
    89 /// Is always a table with present flag names as keys with true values.
       
    90 /// Not present flags are not present in table either.
       
    91 /// Not recognized values, if present, will be stored as a number in a first sequential table member (table[1]).
       
    92 void luaL_pushenum_multi (lua_State *L, enum_value_t value, const string2enum_t *set)
       
    93 {
       
    94 	enum_value_t matched = 0;
       
    95 	lua_newtable (L);
       
    96 	while (set->string) {
       
    97 		if (value & set->value) {
       
    98 			matched |= set->value & value;
       
    99 			lua_pushstring (L, set->string);
       
   100 			lua_pushboolean (L, 1);
       
   101 			lua_settable (L, -3);
       
   102 		}
       
   103 		++set;
       
   104 	}
       
   105 	if (value ^ matched) {
       
   106 		lua_pushinteger (L, 1);
       
   107 		lua_pushinteger (L, value ^ matched);
       
   108 		lua_settable (L, -3);
       
   109 	}
       
   110 }
       
   111 
       
   112 void *luaL_malloc (lua_State *L, size_t size)
       
   113 {
       
   114 	void      *ud;
       
   115 	lua_Alloc  allocf = lua_getallocf (L, &ud);
       
   116 	return (*allocf) (ud, NULL, 0, size);
       
   117 }
       
   118 
       
   119 void *luaL_realloc (lua_State *L, void *ptr, size_t osize, size_t nsize)
       
   120 {
       
   121 	void      *ud;
       
   122 	lua_Alloc  allocf = lua_getallocf (L, &ud);
       
   123 	return (*allocf) (ud, ptr, osize, nsize);
       
   124 }
       
   125 
       
   126 void  luaL_free (lua_State *L, void *ptr)
       
   127 {
       
   128 	void      *ud;
       
   129 	lua_Alloc  allocf = lua_getallocf (L, &ud);
       
   130 	(*allocf) (ud, ptr, 1, 0);
       
   131 }
       
   132