[examples] Fix non-table response handling in shortener
Reported by Mikael Berthe
/* Copyright 2009 Myhailo Danylenko
This code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <strings.h>
#include <lua.h>
#include <lauxlib.h>
#include "util.h"
/// Utility Lua Routines
/// To handle conversion of enums and flag fields to/from human-readable strings.
enum_value_t string2enum (const char *string, const string2enum_t *set)
{
while (set->string) {
if (!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;
}
/// argument enum field
/// String that will be converted to number or just plain number, that will be passed as is.
/// Note, that if enum name is not recognized no error will be raised and default vale will be used.
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);
}
/// return enum field
/// String. If no string found, plain number will be returned.
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);
}
/// argument flags field
/// Can be just plain number, then it is passed as is.
/// Can be a string, then it is recognized as a single enabled flag.
/// Or can be a table of the following format:
/// * integer keys should have string values, that will be used as enabled flag names or numerical values, that will be just ORed;
/// * string keys should be flag names, that will be enabled, if corresponding value contains true 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);
}
return retval;
} else
luaL_argerror (L, index, "integer, string, or table of ones expected");
return 0; // never happens
}
/// returned flags field
/// Is always a table with present flag names as keys with true values.
/// Not present flags are not present in table either.
/// Not recognized values, if present, will be stored as a number in a first sequential table member (table[1]).
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);
}