====== honeysuckle ====== honeysuckle is a C library intended to make creating Lua bindings simpler. It was originally a core part of the honey code, but was split out into its own library because it is useful in many other contexts. It provides functions for argument parsing, table creation and processing, error throwing and handling, string wrangling, and registry operations. ===== hs_parse_args ===== void hs_parse_args( lua_State *L, ...); === Stack Modifications === [-0, +0, v][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to parse arguments from. * ''...'': A series of ''struct hs_arg'' construction macros. === Return Value === None. === Description === This function reads arguments provided on the stack into the variables provided to it in the argument list, performing type-checking as it proceeds. If the wrong number of arguments is provided, or if there is a type mismatch between the expected type provided to this function and the actual type on the stack, it will throw an error message detailing that mismatch. Below is a table of all of the available macros for parsing. Each function-like macro takes a single variable (//not// a pointer or a constant) whose type must be //exactly// that listed under "variable type" or undefined behavior will result. Your compiler will probably complain if there is a mismatch. ^ macro ^ expected stack type ^ variable type ^ variable value after call ^ | hs_bool(x) | boolean | bool | the boolean value | | hs_int(x) | number, interpreted as integer | lua_Integer | the integer value | | hs_num(x) | number | lua_Number | the number value | | hs_str(x) | string | char * | pointer to the string data on the stack | | hs_tbl(x) | table | int | stack index of the table | | hs_func(x) | function | int | stack index of the function | | hs_cfunc(x) | function, interpretable as C function | lua_CFunction | pointer to the function | | hs_user(x) | userdata | void * | pointer to the memory block | | hs_light(x) | light userdata | void * | the pointer value | | hs_nil(x) | nil value | int | stack index of the nil value | | hs_any(x) | any value | int | stack index of the value | === Example === The following would be used to create a Lua function that expects arguments like ''(number, string, table)''. lua_Number n; char *string; int table_index; hs_parse_args(L, hs_num(n), hs_str(string), hs_tbl(table_index)); ===== hs_parse_overloaded ===== int hs_parse_overloaded( lua_State *L, ...); === Stack Modifications === [-0, +0, v][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to parse arguments from. * ''...'': A series of ''hs_overload()'' macros. === Return Value === The zero-based index of the overload option selected. === Description === This function allows you to create overloaded Lua bindings with a very similar syntax to ''hs_parse_args()''. It accepts a series of ''hs_overload()'' macros that in turn accept a series of ''struct hs_arg'' construction macros, exactly as described above. It will attempt to match each provided overload option to the given arguments, returning as soon as it finds one. This function is subject to the same cautions about types discussed above. Please note that the process of attempting to match an overload may mutate the values in the provided variables, and so you should not rely on them having the same value after a call as before, even if they do not participate in the actually selected overload. === Example === lua_Integer i; lua_Number n; char *string; int choice = hs_parse_overloaded( L, hs_overload(hs_int(i)), hs_overload(hs_num(n), hs_str(string)) ); if (choice == 0) { /* n and string are undefined! */ /* do something with i... */ } else { /* i is undefined! */ /* do something with n and string... */ } ===== hs_create_table ===== int hs_create_table( lua_State *L, ...); === Stack Modifications === [-?, +1, m][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to operate on. * ''...'': Any number of ''struct hs_tbl_entry'' construction macros. === Return Value === The stack index of the created table. === Description === Create Lua tables. This function takes a series of key/value macros and constructs a table containing those keys and values. Each macro takes the form ''hs_[key type]_[value_type](key, value)'', as illustrated in the table below, Arguments to these values are passed by value, so concerns about bit alignment are not relevant here. Macros dealing with table, function, and userdata types each take an integer. This is the stack index of the value on the Lua stack to use. These values are popped before returning. Please note both that this means that nesting tables is quite trivial (by simply calling ''hs_create_table()'' inside one of the macros) and that nesting tables in this way requires a subtable to have all of its stack-indexed keys and values pushed after any such keys or values used in an ancestor table, or else the indices needed to construct that ancestor will be modified and likely will no longer be valid. | | ^ Value Type ^^^^^^^^^ | | ^ boolean ^ integer ^ number ^ string ^ table ^ function ^ C function ^ userdata ^ light userdata ^ ^ Key Type ^ boolean | hs_bool_bool(bool, bool) | hs_bool_int(bool, lua_Integer) | hs_bool_num(bool, lua_Number) | hs_bool_str(bool, char *) | hs_bool_tbl(bool, int) | hs_bool_func(bool, int) | hs_bool_cfunc(bool, lua_CFunction) | hs_bool_user(bool, int) | hs_bool_light(bool, void *) | ^ ::: ^ integer | hs_int_bool(lua_Integer, bool) | hs_int_int(lua_Integer, lua_Integer) | hs_int_num(lua_Integer, lua_Number) | hs_int_str(lua_Integer, char *) | hs_int_tbl(lua_Integer, int) | hs_int_func(lua_Integer, int) | hs_int_cfunc(lua_Integer, lua_CFunction) | hs_int_user(lua_Integer, int) | hs_int_light(lua_Integer, void *) | ^ ::: ^ number | hs_num_bool(lua_Number, bool) | hs_num_int(lua_Number, lua_Integer) | hs_num_num(lua_Number, lua_Number) | hs_num_str(lua_Number, char *) | hs_num_tbl(lua_Number, int) | hs_num_func(lua_Number, int) | hs_num_cfunc(lua_Number, lua_CFunction) | hs_num_user(lua_Number, int) | hs_num_light(lua_Number, void *) | ^ ::: ^ string | hs_str_bool(char *, bool) | hs_str_int(char *, lua_Integer) | hs_str_num(char *, lua_Number) | hs_str_str(char *, char *) | hs_str_tbl(char *, int) | hs_str_func(char *, int) | hs_str_cfunc(char *, lua_CFunction) | hs_str_user(char *, int) | hs_str_light(char *, void *) | ^ ::: ^ table | hs_tbl_bool(int, bool) | hs_tbl_int(int, lua_Integer) | hs_tbl_num(int, lua_Number) | hs_tbl_str(int, char *) | hs_tbl_tbl(int, int) | hs_tbl_func(int, int) | hs_tbl_cfunc(int, lua_CFunction) | hs_tbl_user(int, int) | hs_tbl_light(int, void *) | ^ ::: ^ function | hs_func_bool(int, bool) | hs_func_int(int, lua_Integer) | hs_func_num(int, lua_Number) | hs_func_str(int, char *) | hs_func_tbl(int, int) | hs_func_func(int, int) | hs_func_cfunc(int, lua_CFunction) | hs_func_user(int, int) | hs_func_light(int, void *) | ^ ::: ^ C function | hs_cfunc_bool(lua_CFunction, bool) | hs_cfunc_int(lua_CFunction, lua_Integer) | hs_cfunc_num(lua_CFunction, lua_Number) | hs_cfunc_str(lua_CFunction, char *) | hs_cfunc_tbl(lua_CFunction, int) | hs_cfunc_func(lua_CFunction, int) | hs_cfunc_cfunc(lua_CFunction, lua_CFunction) | hs_cfunc_user(lua_CFunction, int) | hs_cfunc_light(lua_CFunction, void *) | ^ ::: ^ userdata | hs_user_bool(int, bool) | hs_user_int(int, lua_Integer) | hs_user_num(int, lua_Number) | hs_user_str(int, char *) | hs_user_tbl(int, int) | hs_user_func(int, int) | hs_user_cfunc(int, lua_CFunction) | hs_user_user(int, int) | hs_user_light(int, void *) | ^ ::: ^ light userdata | hs_light_bool(void *, bool) | hs_light_int(void *, lua_Integer) | hs_light_num(void *, lua_Number) | hs_light_str(void *, char *) | hs_light_tbl(void *, int) | hs_light_func(void *, int) | hs_light_cfunc(void *, lua_CFunction) | hs_light_user(void *, int) | hs_light_light(void *, void *) | === Example === The following constructs the table { debugLevel=0, logfile='output.log', someUserdata=[userdata], myTable={ hello='world' } }. lua_newuserdata(L, sizeof(char)); int user_index = lua_gettop(L); hs_create_table(L, hs_str_int("debugLevel", 0), hs_str_str("logfile", "output.log"), hs_str_user("someUserdata", user_index), hs_str_tbl("myTable", hs_create_table( L, hs_str_str("hello", "world"), )); ===== hs_process_table ===== void hs_process_table( lua_State *L, int table_index, ...); === Stack Modifications === [-0, +0, e][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to operate on. * ''table_index'': The stack index of the table to process. * ''...'': List of key processor macros. === Return Value === None. === Description === This function is intended to create Lua bindings that can be called like ''someBinding{debug=true, verbosity=6, logfile='log.txt'}''. To that end, it accepts a list of value-processing macros, which are listed below. Each accepts as arguments a string to check as a key in the table, a callback function pointer (whose signature is different for each type -- see below), and a void pointer to some additional data that may be used by the callbacks. ^ value type ^ callback signature ^ macro ^ | boolean | void cb(bool, void*) | hs_process_bool(key, callback, data) | | integer | void cb(int, void*) | hs_process_int(key, callback, data) | | number | void cb(lua_Number, void*) | hs_process_num(key, callback, data) | | string | void cb(const char*, void*) | hs_process_str(key, callback, data) | For the extremely common case of simply setting a variable, there are provided the functions ''hs_pt_set_bool'', ''hs_pt_set_int'', ''hs_pt_set_num'', and ''hs_pt_set_str'', which will cast the provided void pointer to ''bool'', ''lua_Integer'', ''lua_Number'', or ''const char *'', respectively, and then set that value to the value in the table. This function may throw an error if the provided index is not valid or is not a table. It may trigger metamethods in extracting values. === Example === void open_logfile(const char *logfile, void *settings) { // do something to open and configure the logfile } // tbl_index comes from somewhere... struct settings { bool debug; lua_Integer verbosity; lua_Number epsilon; }; struct settings s; hs_process_table(L, tbl_index, hs_process_int("verbosity", hs_pt_set_int, &(s.verbosity)), hs_process_bool("debug", hs_pt_set_bool, &(s.debug)), hs_process_str("logfile", set_logfile, &s), hs_process_num("epsilon", hs_pt_set_num, &(s.epsilon)) ); ===== hs_pushstring ===== void hs_pushstring( lua_State *L, const char *format_string, ...); === Stack Modifications === [-0, +1, m][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to operate on. * ''format_string'': A printf format string to construct the string to push. * ''...'': printf format options. === Return Value === None. === Description === This function makes it simple to push printf-formatted strings to the Lua stack. Its syntax is exactly that of sprintf, except the destination is a ''lua_State'' pointer, rather than a string buffer. === Example === const char name[] = "Kelly"; int hours = 10; int minutes = 5; hs_pushstring(L, "hello, %s. the current time is %d:%02d.", name, hours, minutes); ===== hs_vpushstring ===== void hs_vpushstring( lua_State *L, const char *format_string, va_list args); === Stack Modifications === [-0, +0, m][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to operate on. * ''format_string'': A printf format string to construct the string to push. * ''args'': List of printf options in a variadic argument list. === Return Value === None. === Description === Similar to ''hs_pushstring()'' above. Its syntax is exactly that of vsprintf, except the destination is a ''lua_State'' pointer, rather than a string buffer. ===== hs_throw_error ===== void hs_vpushstring( lua_State *L, const char *format_string, ...); === Stack Modifications === [-0, +0, v][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': The Lua state to operate on. * ''format_string'': A printf format string to construct the string to push. * ''...'': printf options. === Return Value === None, but by its nature this function will not return and instead makes a long jump to the current error handler. === Description === Similar to ''hs_pushstring()'' above, but pushes the string and then immediately throws an error with it. Useful for constructing complex error messages. This function may also throw a memory-related error if string creation fails. ===== hs_traceback ===== void hs_traceback(lua_State *L); === Stack Modifications === [-(0|1), +(0|1), -][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': the Lua state to inspect === Return Value === None. === Description === This function produces a call traceback string to go with an error message provided to it, or keeps the "error message" intact if it is not a string. It is generally not intended to be called manually, but rather provided to ''lua_pcall()'' as an error handler. ===== hs_call ===== int hs_call( lua_State *L, int nargs, int nret); === Stack Modifications === [-(nargs+1), +(nret|1), -][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': the Lua state to call within. * ''nargs'': the number of arguments to pop from the stack. * ''nret'': the number of return values to push to the stack. === Return Value === 0 on success, or else one of the Lua error codes: ''LUA_ERRRUN'', ''LUA_ERRMEM'', or ''LUA_ERRERR''. === Description === This function is exactly the same as ''lua_pcall'', with the same return values, except that it automatically pushes ''hs_traceback()'' to use as an error handler and does not accept a different error handler. ===== hs_rstore ===== int hs_rstore(lua_State *L); === Stack Modifications === [-1, +0, m][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': the Lua state to operate on. === Return Value === The reference key. === Description === This is a macro wrapper around ''luaL_ref()'' that always uses the Lua registry table. It is provided for convenience. ===== hs_rload ===== void hs_rload( lua_State *L, int reference); === Stack Modifications === [-0, +1, -][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': the Lua state to operate on. * ''reference'': A reference key returned by ''hs_rstore()''. === Return Value === None. === Description === This is a macro wrapper around ''lua_rawgeti()'' that always gets values from the Lua registry table. It is provided for convenience. ===== hs_rdel ===== void hs_rdel( lua_State *L, int reference); === Stack Modifications === [-0, +0, -][//[[Stack Modification Indicator|?]]//] === Parameters === * ''L'': the Lua state to operate on. * ''reference'': a reference key returned by ''hs_rstore()''. === Return Value === The reference key. === Description === This is a macro wrapper around ''luaL_unref()'' that always uses the Lua registry table. It is provided for convenience.