#include "common.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ honey_result honey_format_string(char** string, char* format_string, ...) { honey_result res; va_list args, args_; va_start(args, format_string); va_copy(args_, args); int string_size = vsnprintf(NULL, 0, format_string, args_); va_end(args_); *string = malloc((string_size+1) * sizeof(char)); if (*string == NULL) res = HONEY_MEMORY_ALLOCATION_ERROR; else { vsnprintf(*string, string_size+1, format_string, args); res = HONEY_OK; } va_end(args); return res; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static void honey_lua_arg_error(lua_State* L, char* expected_type, int position) { char* error_message; honey_result result; char* got_type = lua_typename(L, lua_type(L, position)); result = honey_format_string(&error_message, "bad argument in position %d: " "expected %s, but got %s instead.", position, expected_type, got_type); if (result != HONEY_OK) { lua_pushstring(L, "error allocating memory for error message :("); } else { lua_pushstring(L, error_message); free(error_message); } lua_error(L); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_lua_parse_arguments(lua_State* L, int n, ...) { va_list args; va_start(args, n); for (int i=1; i<=n; i++) { honey_lua_type expected_type = va_arg(args, honey_lua_type); switch (expected_type) { case HONEY_BOOLEAN: if (!lua_isboolean(L, i)) honey_lua_arg_error(L, "boolean", i); { bool* result = va_arg(args, bool*); *result = lua_toboolean(L, i); } break; case HONEY_INTEGER: if (!lua_isnumber(L, i)) honey_lua_arg_error(L, "integer", i); { int* result = va_arg(args, int*); *result = lua_tointeger(L, i); } break; case HONEY_NUMBER: if (!lua_isnumber(L, i)) honey_lua_arg_error(L, "number", i); { float* result = va_arg(args, float*); *result = lua_tonumber(L, i); } break; case HONEY_STRING: if (!lua_isstring(L, i)) honey_lua_arg_error(L, "string", i); { char** result = va_arg(args, char**); *result = lua_tostring(L, i); } break; case HONEY_TABLE: if (!lua_istable(L, i)) honey_lua_arg_error(L, "table", i); break; case HONEY_FUNCTION: if (!lua_isfunction(L, i)) honey_lua_arg_error(L, "function", i); break; case HONEY_NIL: if (!lua_isnil(L, i)) honey_lua_arg_error(L, "nil", i); break; case HONEY_USERDATA: if (!lua_isuserdata(L, i)) honey_lua_arg_error(L, "userdata", i); { void** result = va_arg(args, void**); *result = lua_touserdata(L, i); } break; case HONEY_LIGHTUSERDATA: if (!lua_isuserdata(L, i)) honey_lua_arg_error(L, "light userdata", i); { void** result = va_arg(args, void**); *result = lua_touserdata(L, i); } break; case HONEY_ANY: break; default: /* should never get here! */ break; } } va_end(args); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ bool honey_lua_validate_types(lua_State* L, unsigned int n_types, ...) { va_list args; va_start(args, n_types); for (int i=0; iwindow, true); return 0; }