Hi Folks,

I've implemented the core features of the Lua data library; the patch
is attached. Luadata provides C and Lua APIs to handle binary data
using Lua scripts. Here is a briefly description of those:

1. Lua API:

1.1 creation

- data.new(table)

Returns a new data object initialized with the given byte array. For example:

d1 = data.new{0xFF, 0xFE, 0x00} --> returns a data object with 3 bytes.

1.2 layout

- data.layout(table)

Returns a new layout table based on table argument, which should have
the following formats for its fields:

(i) field = {<offset>, <length> [, <endian>]} or
(ii) field = {offset = <offset>, length = <length> [endian = <endian>]}

Where, field is the name of the field, <offset> is the offset in bits
(MSB 0), <length> is the length in bits, endian is a string that
indicates the field endianness ('host', 'net', 'little', 'big'). The
default value for endian is 'big'.

Here are a couple examples:

(i) l1 = data.layout{msb = {0, 1}, uint32 = {0, 32}, uint64le = {0,
64, 'little'}}

(ii) l2 = data.layout{msb = {offset = 0, length = 1},
  net_unaligned_uint16 = {offset = 1, length = 16, endian = 'net'}}

- d:layout(layout | table)

Applies a layout table on a given data object. If a regular table is
passed, it calls data.layout(table) first. For example:

d1:layout(l1) -- applies l1 layout into d1 data object
d2:layout{byte = {0, 8}} -- creates and applies a new layout into d2 data object

2. API C

2.1 creation

- int ldata_newref(lua_State *L, void *ptr, size_t size);

Creates a new data object pointing to ptr (without copying it), leaves
the data object on the top of the Lua stack and returns a reference
for it. The data object will not be garbage-collected until it is
unreferred.

2.2 deletion

- void ldata_unref(lua_State *L, int ref);

Removes the ptr from the data object and releases the data-object
reference, allowing it to be garbage-collected. After that, it is safe
to free the ptr pointer.

Regards,
--
Lourival Vieira Neto
Index: lib/lua/data/Makefile
===================================================================
RCS file: lib/lua/data/Makefile
diff -N lib/lua/data/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/Makefile	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,9 @@
+LUA_MODULES=	data
+
+LUA_SRCS.data=	luadata.c
+LUA_SRCS.data+=	data.c
+LUA_SRCS.data+=	layout.c
+LUA_SRCS.data+=	luautil.c
+LUA_SRCS.data+=	binary.c
+
+.include <bsd.lua.mk>
Index: lib/lua/data/binary.c
===================================================================
RCS file: lib/lua/data/binary.c
diff -N lib/lua/data/binary.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/binary.c	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <limits.h>
+
+#include <sys/param.h>
+
+#include "binary.h"
+
+#define BYTE_MAX	UCHAR_MAX
+#define UINT64_BIT	(64)
+
+inline static void
+set_bits(uint64_t *value, uint64_t clear_mask, uint64_t set_mask)
+{
+	*value &= clear_mask;
+	*value |= set_mask;
+}
+
+#define CONTIGUOUS_BITS(widt, truncated)	(width - truncated)
+
+static void
+expand(uint64_t *value, size_t width, size_t msb_offset, byte_t truncated)
+{
+	size_t contiguous = CONTIGUOUS_BITS(width, truncated);
+
+	size_t trunc_msb_offset = BYTE_BIT - truncated;
+	size_t trunc_lsb_offset = contiguous + trunc_msb_offset;
+
+	size_t clear_offset = msb_offset + truncated;
+
+	uint64_t clear_mask = UINT64_MAX >> clear_offset;
+	uint64_t trunc_mask = *value >> trunc_lsb_offset << contiguous;
+
+	set_bits(value, clear_mask, trunc_mask);
+}
+
+static void
+contract(uint64_t *value, size_t width, size_t msb_offset, byte_t truncated)
+{
+	size_t contiguous = CONTIGUOUS_BITS(width, truncated);
+
+	size_t trunc_lsb_offset = BYTE_BIT - truncated;
+	size_t trunc_msb_offset = contiguous + trunc_lsb_offset;
+
+	size_t clear_offset = msb_offset + truncated;
+
+	uint64_t clear_mask = UINT64_MAX << clear_offset;
+	uint64_t trunc_mask = *value << trunc_msb_offset >> contiguous;
+
+	set_bits(value, clear_mask, trunc_mask);
+}
+
+#define TRUNCATED_BITS(width)		(width % BYTE_BIT)
+
+#define VALUE_MSB_OFFSET(width)		(UINT64_BIT - width)
+
+static void
+swap_bytes_in(uint64_t *value, size_t width)
+{
+	size_t msb_offset = VALUE_MSB_OFFSET(width);
+
+	*value <<= msb_offset;
+
+	*value = bswap64(*value);
+
+	byte_t truncated = TRUNCATED_BITS(width);
+	if (truncated > 0)
+		expand(value, width, msb_offset, truncated);
+}
+
+static void
+swap_bytes_out(uint64_t *value, size_t width)
+{
+	size_t msb_offset = VALUE_MSB_OFFSET(width);
+
+	*value = bswap64(*value);
+
+	byte_t truncated = TRUNCATED_BITS(width);
+	if (truncated > 0)
+		contract(value, width, msb_offset, truncated);
+
+	*value >>= msb_offset;
+}
+
+#define MSB_OFFSET(offset)		(offset % BYTE_BIT)
+
+#define LSB_OFFSET(width, msb_offset)					\
+	MAX((ssize_t) (BYTE_BIT - msb_offset - width), 0)
+
+#define BYTE_POSITION(offset)		(offset / BYTE_BIT)
+
+#define OVERFLOW_BITS(width, msb_offset, lsb_offset) 			\
+	(width - (BYTE_BIT - msb_offset - lsb_offset))
+
+#define MASK(msb_offset, lsb_offset) 					\
+	((byte_t) BYTE_MAX >> (msb_offset + lsb_offset) << lsb_offset)
+
+#define OVERFLOW_LSB_OFFSET(overflow)	(BYTE_BIT - overflow)
+
+#define NEED_SWAP(width, endian) 					\
+	(width > BYTE_BIT && endian == LITTLE_ENDIAN)
+
+uint64_t
+binary_get_uint64(byte_t *bytes, size_t offset, size_t width, int endian)
+{
+	size_t msb_offset = MSB_OFFSET(offset);
+	size_t lsb_offset = LSB_OFFSET(width, msb_offset);
+	size_t pos        = BYTE_POSITION(offset);
+	size_t overflow   = OVERFLOW_BITS(width, msb_offset, lsb_offset);
+	byte_t mask       = MASK(msb_offset, lsb_offset);
+
+	uint64_t value = (byte_t) (bytes[ pos ] & mask) >> lsb_offset;
+
+	for (; overflow >= BYTE_BIT; overflow -= BYTE_BIT)
+		value = (value << BYTE_BIT) | bytes[ ++pos ];
+
+	if (overflow > 0) {
+		/* assertion: overflow < BYTE_BIT */
+		size_t overflow_lsb_offset = OVERFLOW_LSB_OFFSET(overflow);
+
+		value <<= overflow;
+		value  |= (byte_t) bytes[ ++pos ] >> overflow_lsb_offset;
+	}
+
+	if (NEED_SWAP(width, endian))
+		swap_bytes_in(&value, width);
+
+	return value;
+}
+
+void
+binary_set_uint64(byte_t *bytes, size_t offset, size_t width, int endian, uint64_t value)
+{
+	size_t msb_offset = MSB_OFFSET(offset);
+	size_t lsb_offset = LSB_OFFSET(width, msb_offset);
+	size_t pos        = BYTE_POSITION(offset);
+	size_t overflow   = OVERFLOW_BITS(width, msb_offset, lsb_offset);
+	byte_t clear_mask = ~MASK(msb_offset, lsb_offset);
+
+	if (NEED_SWAP(width, endian))
+		swap_bytes_out(&value, width);
+
+	bytes[ pos ] &= clear_mask;
+	bytes[ pos ] |= (uint64_t) value << lsb_offset >> overflow;
+
+	for (; overflow >= BYTE_BIT; overflow -= BYTE_BIT)
+		bytes[ ++pos ] = (uint64_t) value >> (overflow - BYTE_BIT);
+
+	if (overflow > 0) {
+		/* assertion: overflow < BYTE_BIT */
+		size_t overflow_lsb_offset = OVERFLOW_LSB_OFFSET(overflow);
+		byte_t overflow_clear_mask = ~(BYTE_MAX << overflow_lsb_offset);
+
+		bytes[ ++pos ] &= overflow_clear_mask;
+		bytes[   pos ] |= value << overflow_lsb_offset;
+	}
+}
Index: lib/lua/data/binary.h
===================================================================
RCS file: lib/lua/data/binary.h
diff -N lib/lua/data/binary.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/binary.h	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _BINARY_H_
+#define _BINARY_H_
+
+#include <sys/endian.h>
+
+#ifdef _KERNEL
+#include <sys/types.h>
+#else
+#include <stddef.h>
+#include <stdint.h>
+#endif
+
+#define BYTE_BIT	CHAR_BIT
+
+typedef unsigned char byte_t;
+
+uint64_t binary_get_uint64(byte_t *, size_t, size_t, int);
+
+void binary_set_uint64(byte_t *, size_t, size_t, int, uint64_t);
+
+#endif /* _BINARY_H_ */
Index: lib/lua/data/data.c
===================================================================
RCS file: lib/lua/data/data.c
diff -N lib/lua/data/data.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/data.c	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <lauxlib.h>
+
+#include "luautil.h"
+
+#include "data.h"
+
+#include "binary.h"
+#include "layout.h"
+
+#define LUA_INTEGER_BYTE	(sizeof(lua_Integer))
+#define LUA_INTEGER_BIT		(LUA_INTEGER_BYTE * BYTE_BIT)
+
+inline static bool
+check_limits(data_t *data, layout_entry_t *entry)
+{
+	return entry->length <= LUA_INTEGER_BIT &&
+		entry->offset + entry->length <= data->length;
+}
+
+inline static bool
+check_entry(data_t *data, layout_entry_t *entry)
+{
+	return entry != NULL && check_limits(data, entry);
+}
+
+inline static layout_entry_t *
+get_entry(lua_State *L, data_t *data, int key_ix)
+{
+	if (!luau_isvalidref(data->layout))
+		return NULL;
+
+	return layout_get_entry(L, data->layout, key_ix);
+}
+
+data_t *
+data_new(lua_State *L, void *ptr, size_t size, bool free)
+{
+	data_t *data = lua_newuserdata(L, sizeof(data_t));
+
+	data->ptr    = ptr;
+	data->size   = size;
+	data->length = size * BYTE_BIT;
+	data->layout = LUA_REFNIL;
+	data->free   = free;
+
+	luaL_getmetatable(L, DATA_USERDATA);
+	lua_setmetatable(L, -2);
+	return data;
+}
+
+inline data_t *
+data_check(lua_State *L, int index)
+{
+	return (data_t *) luaL_checkudata(L, index, DATA_USERDATA);
+}
+
+inline void
+data_apply_layout(lua_State *L, data_t *data, int layout_ix)
+{
+	luau_unref(L, data->layout);
+	lua_pushvalue(L, layout_ix);
+	data->layout = luau_ref(L);
+}
+
+#define BINARY_PARMS(data, entry)					\
+	data->ptr, entry->offset, entry->length, entry->endian
+
+int
+data_get_field(lua_State *L, data_t *data, int key_ix)
+{
+	if (data->ptr == NULL)
+		return 0;
+
+	layout_entry_t *entry = get_entry(L, data, key_ix);
+	if (!check_entry(data, entry))
+		return 0;
+
+	/* assertion: LUA_INTEGER_BIT <= 64 */
+	lua_Integer value = binary_get_uint64(BINARY_PARMS(data, entry));
+	lua_pushinteger(L, value);
+	return 1;
+}
+
+void
+data_set_field(lua_State *L, data_t *data, int key_ix, lua_Integer value)
+{
+	if (data->ptr == NULL)
+		return;
+
+	layout_entry_t *entry = get_entry(L, data, key_ix);
+	if (!check_entry(data, entry))
+		return;
+
+	binary_set_uint64(BINARY_PARMS(data, entry), value);
+}
Index: lib/lua/data/data.h
===================================================================
RCS file: lib/lua/data/data.h
diff -N lib/lua/data/data.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/data.h	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _DATA_H_
+#define _DATA_H_
+
+#ifndef _KERNEL
+#include <stddef.h>
+#include <stdbool.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <lua.h>
+
+#include "layout.h"
+
+#define DATA_LIB	"data"
+#define DATA_USERDATA	"data.data"
+
+typedef struct {
+	void  *ptr;
+	size_t size;
+	size_t length;
+	int    layout;
+	bool   free;
+} data_t;
+
+data_t * data_new(lua_State *, void *, size_t, bool);
+
+data_t * data_check(lua_State *, int);
+
+void data_apply_layout(lua_State *, data_t *, int);
+
+int data_get_field(lua_State *, data_t *, int);
+
+void data_set_field(lua_State *, data_t *, int, lua_Integer);
+
+#endif /* _DATA_H_ */
Index: lib/lua/data/filter.lua
===================================================================
RCS file: lib/lua/data/filter.lua
diff -N lib/lua/data/filter.lua
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/filter.lua	17 Jan 2014 11:47:53 -0000
@@ -0,0 +1,20 @@
+function filter(d)
+	-- store d in a global
+	gd = d
+	d:layout{
+		-- most significant 4-bytes
+		uint4_msb = {0,4},
+		-- inner 16-bytes
+		uint16    = {4, 16},
+		-- least significant 4-bytes
+		uint4_lsb = {20, 4}
+	}
+	return	d.uint4_msb == 0xa    and
+		d.uint16    == 0xbcde and
+		d.uint4_lsb == 0xf
+end
+
+function access_global_data()
+	-- should return nil if ldata_unref(d) has been called from C
+	return gd.uint16
+end
Index: lib/lua/data/layout.c
===================================================================
RCS file: lib/lua/data/layout.c
diff -N lib/lua/data/layout.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/layout.c	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <lauxlib.h>
+
+#include "luautil.h"
+
+#include "layout.h"
+
+inline static layout_entry_t *
+check_entry(lua_State *L, int index)
+{
+	return (layout_entry_t *) luaL_checkudata(L, index, LAYOUT_ENTRY_USERDATA);
+}
+
+inline static void
+init_layout(layout_entry_t *entry)
+{
+	entry->offset = 0;
+	entry->length = 0;
+	entry->endian = LAYOUT_ENDIAN_DEFAULT;
+}
+
+static void
+load_endian(lua_State *L, layout_entry_t *entry)
+{
+	const char *endian = lua_tostring(L, -1);
+
+	if (endian[0] == 'n' || endian[0] == 'b')
+		entry->endian = BIG_ENDIAN;
+	else if (endian[0] == 'l')
+		entry->endian = LITTLE_ENDIAN;
+	else if (endian[0] == 'h')
+		entry->endian = BYTE_ORDER;
+}
+
+/* format: {<offset>, <length>, <endian>, <step>} */
+static void
+load_entry_numbered(lua_State *L, layout_entry_t *entry)
+{
+	size_t array_len = lua_objlen(L, -1);
+
+	if (array_len >= 1)
+		entry->offset = luau_getarray_integer(L, -1, 1);
+	if (array_len >= 2)
+		entry->length = luau_getarray_integer(L, -1, 2);
+	if (array_len >= 3) {
+		luau_getarray(L, -1, 3);
+		load_endian(L, entry);
+		lua_pop(L, 1);
+	}
+}
+
+/* format: {offset = <offset>, length = <length>, endian = <endian>, step = <step>} */
+static void
+load_entry_named(lua_State *L, layout_entry_t *entry)
+{
+	lua_getfield(L, -1, "offset");
+	if (lua_isnumber(L, -1))
+		entry->offset = lua_tointeger(L, -1);
+	lua_pop(L, 1);
+
+	lua_getfield(L, -1, "length");
+	if (lua_isnumber(L, -1))
+		entry->length = lua_tointeger(L, -1);
+	lua_pop(L, 1);
+
+	lua_getfield(L, -1, "endian");
+	if (lua_isstring(L, -1))
+		load_endian(L, entry);
+	lua_pop(L, 1);
+}
+
+static void
+load_entry(lua_State *L, layout_entry_t *entry)
+{
+	init_layout(entry);
+	load_entry_numbered(L, entry);
+	load_entry_named(L, entry);
+}
+
+static int
+new_entry(lua_State *L, layout_entry_t *entry)
+{
+	layout_entry_t *nentry =
+		(layout_entry_t *) lua_newuserdata(L, sizeof(layout_entry_t));
+
+	luaL_getmetatable(L, LAYOUT_ENTRY_USERDATA);
+	lua_setmetatable(L, -2);
+
+	layout_copy_entry(nentry, entry);
+	return 1;
+}
+
+void
+layout_load(lua_State *L, int index)
+{
+	layout_entry_t entry;
+
+	lua_pushnil(L);  /* first key */
+	while (lua_next(L, index) != 0) {
+		/* uses 'key' (at index -2) and 'value' (at index -1) */
+		load_entry(L, &entry);
+		if (entry.length == 0)
+			lua_pushnil(L);
+		else
+			new_entry(L, &entry);
+
+		/* layout[ key ] = entry */
+		luau_settable(L, index, -3, -1);
+
+		/* removes 'value' and 'entry'; keeps 'key' for next iteration */
+		lua_pop(L, 2);
+	}
+
+	lua_pushboolean(L, true);
+	lua_setfield(L, index, LAYOUT_STAMP);
+}
+
+layout_entry_t *
+layout_get_entry(lua_State *L, int layout_ix, int key_ix)
+{
+	void *entry = NULL;
+
+	luau_getref(L, layout_ix);
+	luau_gettable(L, -1, key_ix);
+	if (lua_isnil(L, -1))
+		goto end;
+
+	entry = check_entry(L, -1);
+
+end:
+	lua_pop(L, 2);
+	return entry;
+}
+
+void
+layout_copy_entry(layout_entry_t *dst, layout_entry_t *src)
+{
+	dst->offset = src->offset;
+	dst->length = src->length;
+	dst->endian = src->endian;
+}
Index: lib/lua/data/layout.h
===================================================================
RCS file: lib/lua/data/layout.h
diff -N lib/lua/data/layout.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/layout.h	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _LAYOUT_H_
+#define _LAYOUT_H_
+
+#ifndef _KERNEL
+#include <stdint.h>
+#include <stdbool.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <sys/endian.h>
+
+#include <lua.h>
+
+#define LAYOUT_ENTRY_USERDATA 	"data.layout.entry"
+
+#define LAYOUT_STAMP 		"__layout_stamp"
+
+#define LAYOUT_ENDIAN_DEFAULT	BIG_ENDIAN
+
+typedef struct {
+	size_t  offset;
+	size_t  length;
+	int     endian;
+} layout_entry_t;
+
+void layout_load(lua_State *, int);
+
+layout_entry_t * layout_get_entry(lua_State *, int, int);
+
+void layout_copy_entry(layout_entry_t *, layout_entry_t *);
+
+#endif /* _LAYOUT_H_ */
Index: lib/lua/data/luadata.c
===================================================================
RCS file: lib/lua/data/luadata.c
diff -N lib/lua/data/luadata.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/luadata.c	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2013, 2014 Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "luadata.h"
+
+#include "luautil.h"
+
+#include "data.h"
+#include "layout.h"
+
+static int
+new_data(lua_State *L)
+{
+	if(!lua_istable(L, 1))
+		return 0;
+
+	size_t len   = lua_objlen(L, 1);
+	char   *data = (char *) luau_malloc(L, len);
+
+	size_t i = 0;
+	lua_pushnil(L);  /* first key */
+	while (lua_next(L, 1) != 0 && i < len) {
+		/* uses 'key' (at index -2) and 'value' (at index -1) */
+		data[ i++ ] = (char) lua_tointeger(L, -1);
+		/* removes 'value'; keeps 'key' for next iteration */
+		lua_pop(L, 1);
+	}
+	data_new(L, (void *) data, len, true);
+
+	return 1;
+}
+
+static int
+new_layout(lua_State *L)
+{
+	if (!lua_istable(L, 1))
+		return 0;
+
+	layout_load(L, 1);
+	return 1;
+}
+
+static int
+apply_layout(lua_State *L)
+{
+	data_t *data = data_check(L, 1);
+
+	if (!lua_istable(L, 2))
+		return 0;
+
+	lua_getfield(L, 2, LAYOUT_STAMP);
+	bool is_layout = (bool) lua_toboolean(L, -1);
+	lua_pop(L, 1);
+
+	if (!is_layout)
+		layout_load(L, 2);
+
+	data_apply_layout(L, data, 2);
+
+	/* return data object */
+	lua_pushvalue(L, 1);
+	return 1;
+}
+
+static int
+gc(lua_State *L)
+{
+	data_t *data = data_check(L, 1);
+
+	if (data->free)
+		luau_free(L, data->ptr, data->size);
+	return 0;
+}
+
+static int
+get_field(lua_State *L)
+{
+	data_t *data = data_check(L, 1);
+
+	lua_getmetatable(L, 1);
+	if (lua_isstring(L, 2)) {
+		/* try object-oriented access first */
+		luau_gettable(L, -1, 2);
+		if (lua_iscfunction(L, -1))
+			/* return this method */
+			return 1;
+		lua_pop(L, 1);
+	}
+
+	return data_get_field(L, data, 2);
+}
+
+static int
+set_field(lua_State *L)
+{
+	data_t *data = data_check(L, 1);
+
+	lua_getmetatable(L, 1);
+	if (lua_isstring(L, 2)) {
+		/* try object-oriented access first */
+		luau_gettable(L, -1, 2);
+		if (lua_iscfunction(L, -1)) {
+			/* shouldn't overwrite a method */
+			lua_pop(L, 1);
+			return 0;
+		}
+	}
+
+	lua_Integer value = lua_tointeger(L, 3);
+
+	data_set_field(L, data, 2, value);
+	return 0;
+}
+
+static const luaL_Reg data_lib[ ] = {
+	{"new"  , new_data},
+	{"layout", new_layout},
+	{NULL    , NULL}
+};
+
+static const luaL_Reg data_m[ ] = {
+	{"layout"    , apply_layout},
+	{"__index"   , get_field},
+	{"__newindex", set_field},
+	{"__gc"      , gc},
+	{NULL        , NULL}
+};
+
+static const luaL_Reg layout_entry_m[ ] = {
+	{NULL, NULL}
+};
+
+int
+luaopen_data(lua_State *L);
+
+int
+luaopen_data(lua_State *L)
+{
+	luaL_newmetatable(L, DATA_USERDATA);
+	luaL_register(L, NULL, data_m);
+	luaL_register(L, DATA_LIB, data_lib);
+
+	luaL_newmetatable(L, LAYOUT_ENTRY_USERDATA);
+	luaL_register(L, NULL, layout_entry_m);
+
+	return 1;
+}
+
+int
+ldata_newref(lua_State *L, void *ptr, size_t size)
+{
+	data_new(L, ptr, size, false);
+	/* keep the new data object on the stack */
+	lua_pushvalue(L, -1);
+	return luau_ref(L);
+}
+
+void
+ldata_unref(lua_State *L, int r)
+{
+	luau_getref(L, r);
+	data_t *data = data_check(L, -1);
+
+	data->ptr = NULL;
+
+	lua_pop(L, 1);
+	luau_unref(L, r);
+}
+
+#ifdef _MODULE
+#include <sys/lua.h>
+#include <sys/module.h>
+
+MODULE(MODULE_CLASS_MISC, luadata, "lua");
+
+typedef int (*kluaopen_t)(void *) ;
+
+static int
+luadata_modcmd(modcmd_t cmd, void *opaque)
+{
+	int error;
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		error = lua_mod_register(DATA_LIB, (kluaopen_t) luaopen_data);
+		break;
+	case MODULE_CMD_FINI:
+		error = lua_mod_unregister(DATA_LIB);
+		break;
+	default:
+		error = ENOTTY;
+	}
+	return error;
+}
+#endif
Index: lib/lua/data/luadata.h
===================================================================
RCS file: lib/lua/data/luadata.h
diff -N lib/lua/data/luadata.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/luadata.h	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _LUA_DATA_H_
+#define _LUA_DATA_H_
+
+#ifndef _KERNEL
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include <lua.h>
+
+extern int ldata_newref(lua_State *, void *, size_t);
+
+extern void ldata_unref(lua_State *, int);
+
+extern int luaopen_data(lua_State *L);
+
+#endif /* _LUA_DATA_H_ */
Index: lib/lua/data/luautil.c
===================================================================
RCS file: lib/lua/data/luautil.c
diff -N lib/lua/data/luautil.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/luautil.c	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, 2014, Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "luautil.h"
+
+inline static void
+adjust_index(int *index, int factor)
+{
+	if (*index < 0)
+		(*index) -= factor;
+}
+
+void
+luau_getarray(lua_State *L, int index, lua_Integer n)
+{
+	lua_pushinteger(L, n);
+	adjust_index(&index, 1);
+	lua_gettable(L, index);
+}
+
+lua_Integer
+luau_getarray_integer(lua_State *L, int index, lua_Integer n)
+{
+	luau_getarray(L, index, n);
+	lua_Integer result = lua_tointeger(L, -1);
+	lua_pop(L, 1);
+	return result;
+}
+
+void
+luau_gettable(lua_State *L, int index, int field_index)
+{
+	lua_pushvalue(L, field_index);
+	adjust_index(&index, 1);
+	lua_gettable(L, index);
+}
+
+void
+luau_settable(lua_State *L, int index, int field_index, int value_index)
+{
+	lua_pushvalue(L, field_index);
+	adjust_index(&value_index, 1);
+	lua_pushvalue(L, value_index);
+	adjust_index(&index, 2);
+	lua_settable(L, index);
+}
+
+void *
+luau_malloc(lua_State *L, size_t size)
+{
+	void * ud = NULL;
+	lua_Alloc alloc = lua_getallocf(L, &ud);
+	return alloc(ud, NULL, 0, size);
+}
+
+void
+luau_free(lua_State *L, void * ptr, size_t size)
+{
+	void * ud = NULL;
+	lua_Alloc alloc = lua_getallocf(L, &ud);
+	alloc(ud, ptr, size, 0);
+}
Index: lib/lua/data/luautil.h
===================================================================
RCS file: lib/lua/data/luautil.h
diff -N lib/lua/data/luautil.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/luautil.h	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, 2014 Lourival Vieira Neto <[email protected]>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _LUA_UTIL_H_
+#define _LUA_UTIL_H_
+
+#ifndef _KERNEL
+#include <stddef.h>
+#endif
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#define luau_isvalidref(ref)	(ref != LUA_REFNIL && ref != LUA_NOREF)
+
+#define luau_ref(L)		luaL_ref(L, LUA_REGISTRYINDEX)
+#define luau_unref(L, r)	luaL_unref(L, LUA_REGISTRYINDEX, r)
+#define luau_getref(L, r)	lua_rawgeti(L, LUA_REGISTRYINDEX, r)
+
+void luau_getarray(lua_State *, int, lua_Integer);
+
+lua_Integer luau_getarray_integer(lua_State *, int, lua_Integer);
+
+void luau_gettable(lua_State *, int, int);
+
+void luau_settable(lua_State *, int, int, int);
+
+void * luau_malloc(lua_State *, size_t);
+
+void luau_free(lua_State *, void *, size_t);
+
+#endif /* _LUA_UTIL_H_ */
Index: lib/lua/data/test.c
===================================================================
RCS file: lib/lua/data/test.c
diff -N lib/lua/data/test.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/test.c	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,64 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "luadata.h"
+
+typedef unsigned char byte_t;
+
+int main(void)
+{
+	/* create a new Lua state */
+	lua_State *L = luaL_newstate();
+
+	/* open luadata library */
+	luaopen_data(L);
+
+	/* load a script */
+	if (luaL_dofile(L, "filter.lua") != 0)
+		goto err;
+	
+	/* get the filter function */
+	lua_getglobal(L, "filter");
+
+	/* create a new data ptr */
+	size_t  data_size = 3;
+	byte_t *data_ptr  = (byte_t *) malloc(data_size);
+	data_ptr[0] = 0xAB;
+	data_ptr[1] = 0xCD;
+	data_ptr[2] = 0xEF;
+
+	/* create a new data object */
+	int rd = ldata_newref(L, data_ptr, data_size);
+
+	/* call filter(d)*/
+	if (lua_pcall(L, 1, 1, 0) != 0)
+		goto err;
+
+	/* get filter result */
+	bool passed = (bool) lua_toboolean(L, -1);
+
+	/* unregister the Lua data object */
+	ldata_unref(L, rd);
+
+	/* now we can safely free the data pointer */
+	free(data_ptr);
+
+	/* get the access_global_data function */
+	lua_getglobal(L, "access_global_data");
+
+	/* call access_global_data() */
+	if (lua_pcall(L, 0, 1, 0) != 0)
+		goto err;
+
+	/* if global access returned nil and filter has passed; then test passed */
+	if (lua_isnil(L, -1) && passed)
+		printf("test passed ;-)\n");
+
+	return 0;
+err:
+	return 1;
+}
+
Index: lib/lua/data/test.lua
===================================================================
RCS file: lib/lua/data/test.lua
diff -N lib/lua/data/test.lua
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/lua/data/test.lua	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,45 @@
+require "data"
+
+-- create a new data object
+d1 = data.new{0x0f}
+
+-- create and apply a data layout
+d1:layout{byte = {0, 8}, lsb = {7, 1}}
+
+-- access the whole byte 
+assert(d1.byte == 0x0f)
+
+-- set 0 to the least significant bit
+d1.lsb = 0
+
+-- access the whole byte again
+assert(d1.byte == 0x0e)
+
+-- create a new layout
+l = data.layout{
+	uint16be = {0, 16},
+	uint16le = {0, 16, 'l'},
+	uint4    = {16, 4},
+	uint9    = {20, 9},
+	overflow = {32, 1},
+}
+
+-- create a new data object
+d2 = data.new{0xaa, 0xbb, 0xcc, 0xdd}
+
+-- apply the layout 'l' to data 'd2'
+d2:layout(l)
+
+-- access 2 bytes using big-endian ordering
+assert(d2.uint16be == 0xaabb)
+
+-- access 2 bytes using little-endian ordering
+assert(d2.uint16le == 0xbbaa)
+
+-- access 4 bits 
+assert(d2.uint4 == 0xc)
+
+-- access out of bounds
+assert(d2.overflow == nil)
+
+print("test passed ;-)")
Index: sys/modules/luadata/Makefile
===================================================================
RCS file: sys/modules/luadata/Makefile
diff -N sys/modules/luadata/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/modules/luadata/Makefile	17 Jan 2014 11:47:54 -0000
@@ -0,0 +1,18 @@
+.include	"../Makefile.inc"
+
+.PATH:		${S}/../lib/lua/data
+
+KMOD=		luadata
+
+SRCS=		luadata.c
+SRCS+=		data.c
+SRCS+=		layout.c
+SRCS+=		luautil.c
+SRCS+=		binary.c
+
+CPPFLAGS+=	-I${S}/../external/mit/lua/dist/src
+CPPFLAGS+=	-I${S}/modules/lua 
+CPPFLAGS+=	-I${S}/sys
+
+.include <bsd.kmodule.mk>
+

Reply via email to