summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2021-05-23 14:17:27 -0500
committersanine-a <sanine.not@pm.me>2021-05-23 14:17:27 -0500
commit4dc4d9f1d20a73d1e4c399a56c86bf70589b13d9 (patch)
treec1d35031608e22e8ed187c8d3330a3dd57be2c41
create README.md and .gitignore
-rw-r--r--.gitignore1
-rw-r--r--README.md284
2 files changed, 285 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..de37ca5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,284 @@
+---
+layout: base
+title: honeysuckle README
+---
+
+honeysuckle
+===========
+
+A pure C library to make writing Lua bindings simple. honeysuckle provides
+functions to make argument parsing, table operations, error creation and
+handling, string wrangling, and registry operations easy and straightforward
+from within your C code.
+
+Table of contents
+-----------------
+
+- [Installation](#installation)
+- [Usage](#usage)
+- [Development](#development)
+- [License](#license)
+- [Footer](#footer)
+
+Installation
+------------
+
+[(Back to top)](#table-of-contents)
+
+Just copy `honeysuckle.h` and `honeysuckle.c` into your project.
+**honeysuckle** depends on the Lua libraries, so make sure you have them
+installed before using.
+
+Usage
+-----
+
+[(Back to top)](#table-of-contents)
+
+- [Type constants](#type-constants)
+- [Argument parsing](#argument-parsing)
+ - [Overloading](#overloading)
+- [Table construction](#table-construction)
+ - [Enums](#enums)
+- [Table processing](#table-processing)
+- [Errors and error handling](#errors-and-error-handling)
+- [String wrangling](#string-wrangling)
+- [Registry values](#registry-values)
+
+### Type constants
+
+[(Back to top)](#table-of-contents)
+
+These constants are used when honeysuckle needs to know a type to expect.
+
+- `HS_BOOL` - booleans
+- `HS_INT` - integers
+- `HS_NUM` - numbers (double by default)
+- `HS_STR` - strings
+- `HS_TBL` - tables
+- `HS_FUNC` - any function
+- `HS_CFUNC` - C functions specifically
+- `HS_USER` - lua full userdata
+- `HS_LIGHT` - lua light userdata
+- `HS_NIL` - lua's nil
+- `HS_ANY` - any type
+
+`hs_type_to_string()` takes as argument a single type constant and returns a
+const string representing the type.
+
+### Argument parsing
+
+[(Back to top)](#table-of-contents)
+
+`hs_parse_args()` is the primary argument-parsing function. It accepts as
+arguments a lua_State pointer, any number of alternating type constant and
+pointer pairs, and finally `HS_END` to close the arguments. This function
+performs typechecking and in case of an error throws with helpful error
+messages. `hs_parse_args_fast()` does not perform typechecking, and as a
+result has much less friendly error messages.
+
+`HS_TBL`, `HS_FUNC`, `HS_NIL`, and `HS_ANY` do not take a pointer, and are
+simply used to confirm the presence of an argument on the stack.
+
+```C
+int some_lua_binding(lua_State *L)
+{
+ bool b;
+ int i;
+ lua_Number n;
+ char *str;
+ void* user;
+ hs_parse_args(L,
+ HS_BOOL, &b,
+ HS_INT, &i,
+ HS_NUM, &n,
+ HS_STR, &str,
+ HS_USER, &user,
+ HS_END);
+ // do something...
+ return 1;
+}
+```
+
+#### Overloading
+
+There is another function, `hs_parse_overloaded()`, that permits overloaded
+argument parsing. Its syntax is exactly as `hs_parse_args()` except that after
+each `HS_END` you may provide another argument list, and after the final
+argument list you must provide another `HS_END`. This function throws an error
+only if none of the argument lists match the provided arguments.
+
+```C
+int overloaded_lua_binding(lua_State *L)
+{
+ int i;
+ char *str;
+ int choice = hs_parse_overloaded(L,
+ HS_INT, &i, HS_END,
+ HS_STR, &str, HS_END,
+ HS_END);
+ if (choice == 0) {
+ // do something with i
+ // str remains unassigned!!
+ }
+ else {
+ // choice == 1, do something with str
+ // i remains unassigned!!
+ }
+ return 0;
+}
+```
+
+### Table construction
+
+[(Back to top)](#table-of-contents)
+
+`hs_create_table()` takes a lua_State pointer, some number of string key/type
+constant/value triplets, and finally `HS_END`. It returns the stack index of
+the newly created table. Most of the type constants expect their associated
+type (e.g. `HS_INT` expects an `int`, `HS_CFUNC` expects `lua_CFunction`,
+etc.) but `HS_FUNC` and `HS_TBL` expect an integer stack index. `hs_create_
+table()` automatically pops any stack indices provided to it.
+
+```C
+int *ptr; // some pointer
+
+hs_create_table(L,
+ "intVal", HS_INT, 4,
+ "numVal", HS_NUM, 6.0f,
+ "tableVal", HS_TBL, hs_create_table(L,
+ "subTableCFunc", HS_CFUNC, some_lua_binding,
+ "subTableString", HS_STR, "i'm a string!",
+ HS_END),
+ "lightUserdataVal", HS_LIGHT, (void *)ptr,
+ HS_END);
+```
+
+#### Enums
+
+`hs_create_enum()` takes a lua_State pointer, some number of string/integer
+pairs, and finally `HS_END`. It creates a table in which, for each string/int
+pair `tbl[string] = int` and `tbl[int] = string` and returns the stack index
+of said table. `hs_string_to_enum()` uses such a table to convert a string
+literal to enum value and `hs_enum_to_string()` converts enums to strings. In
+case the value does not exist, converting to a string results in NULL and
+converting to an enum results in a negative value.
+
+```C
+enum { VALUE_1, VALUE_2, VALUE_3 } example_t;
+
+int index = hs_create_enum(L,
+ "one", VALUE_1,
+ "two", VALUE_2,
+ "three", VALUE_3,
+ HS_END);
+
+example_t e = hs_string_to_enum(L, index, "one"); // VALUE_1
+char *str = hs_enum_to_string(L, index, VALUE_3); // "three"
+```
+
+### Table processing
+
+[(Back to top)](#table-of-contents)
+
+`hs_process_table()` is intended for creating lua bindings that can be called
+like `set_config{ debug=true, verbosity=2, logfile='run.log' }`. It can only operate on stringly-keyed values.
+
+```C
+void set_verbosity(int value, void *data) { // set verbosity level }
+void set_debug(bool value, void *data) { // set debug }
+void set_logfile(char *value, void *data) { // set log filename }
+void process_any_key(int stack_index, void *data) { // do something }
+
+// tbl_index comes from somewhere...
+
+hs_process_table(L, tbl_index, NULL,
+ "verbosity", HS_INT, set_verbosity,
+ "debug", HS_BOOL, set_debug,
+ "logfile", HS_STR, set_logfile,
+ "extraData", HS_ANY, process_any_key,
+ HS_END);
+```
+
+### Errors and error handling
+
+[(Back to top)](#table-of-contents)
+
+`hs_throw_error()` constructs and throws error messages like printf.
+
+```C
+hs_throw_error(L, "ERROR: %d is not within range", 10);
+```
+
+`hs_traceback()` can be supplied to `lua_pcall()` to get a helpful stack trace
+error message:
+
+```C
+lua_pushcfunction(L, hs_traceback);
+int tr_pos = lua_gettop();
+
+// push function
+// push n arguments
+int result = lua_pcall(L, nargs, nret, tr_pos);
+```
+
+`hs_call()` performs the above, accepting simply a lua_State pointer, int
+nargs, and int nret as arguments. Alternatively, you can use `hs_call_args()`
+which provides the same helpful, contained error messages as `hs_call()` but
+takes arguments explicitly in the call for both function arguments and
+returns:
+
+```C
+// some_function accepts int, str and returns number, boolean
+lua_pushcfunction(L, some_function);
+
+lua_Number n;
+bool b;
+hs_call_args(L,
+ HS_INT, 4, HS_STR, "hello", HS_END,
+ HS_NUM, &n, HS_BOOL, &b, HS_END);
+```
+
+### String wrangling
+
+[(Back to top)](#table-of-contents)
+
+`hs_pushstring()` allows you to push string values using printf format
+strings.
+
+```C
+hs_pushstring(L, "hello there, %s. I hear the current time is %d:%02d", "dylan", 10, 5);
+```
+
+### Registry values
+
+[(Back to top)](#table-of-contents)
+
+honeysuckle provides three macros, `hs_rstore()`, `hs_rload()`, and `hs_
+rdel()` to make registry access easier. These are mostly just thin wrappers
+around `luaL_ref()`, `luaL_unref()` and `lua_rawgeti()` but they come up
+frequently enough that I think these are helpful.
+
+```C
+lua_pushstring(L, "some string");
+int my_string_ref = hs_rstore(L);
+// ...
+hs_rload(L, my_string_ref); // load the value referenced by my_string_ref
+hs_rdel(L, my_string_ref); // done with this reference, remove from the registry table
+```
+
+Development
+-----------
+[(Back to top)](#table-of-contents)
+
+honeysuckle is still very early in development. As the specifics of the build
+process and testing become clearer I'll update this section.
+
+# License
+[(Back to top)](#table-of-contents)
+
+
+honeysuckle is licensed under the [Anti-Capitalist Software License].
+Basically: if you're a single person, a co-op, or a nonprofit, feel free to
+use this. Otherwise, send me an email. c:
+
+[Anti-Capitalist Software License]: https://anticapitalist.software