├── .gitignore ├── GNUmakefile ├── Kbuild ├── Makefile ├── README.md ├── binary.c ├── binary.h ├── ctest.lua ├── data.c ├── data.h ├── handle.c ├── handle.h ├── layout.c ├── layout.h ├── luadata.c ├── luadata.h ├── luadata_core.c ├── luautil.c ├── luautil.h ├── sys └── endian.h ├── test.c └── test.lua /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.o.cmd 3 | *.so 4 | modules.* 5 | bak/ 6 | tmp/ 7 | CVS/ 8 | obj/ 9 | test 10 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-I. -fPIC 3 | LDLIBS=-llua 4 | OBJ=luadata.o data.o handle.o layout.o binary.o luautil.o 5 | 6 | data.so: $(OBJ) 7 | $(CC) -shared -o data.so $(OBJ) $(LDLIBS) 8 | 9 | test: test.c data.so 10 | 11 | clean: 12 | rm -f *.so *.o test || true 13 | -------------------------------------------------------------------------------- /Kbuild: -------------------------------------------------------------------------------- 1 | ccflags-y += -D_KERNEL -D'CHAR_BIT=(8)' \ 2 | -Wno-declaration-after-statement \ 3 | -D'MIN=min' -D'MAX=max' -D'UCHAR_MAX=(255)' -D'UINT64_MAX=((u64)~0ULL)' 4 | 5 | obj-$(CONFIG_LUADATA) += luadata.o 6 | luadata-objs += binary.o data.o handle.o layout.o luadata_core.o luautil.o 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LUA_MODULES= data 2 | 3 | LUA_SRCS.data= luadata.c 4 | LUA_SRCS.data+= data.c 5 | LUA_SRCS.data+= handle.c 6 | LUA_SRCS.data+= layout.c 7 | LUA_SRCS.data+= luautil.c 8 | LUA_SRCS.data+= binary.c 9 | 10 | DATA= data.so 11 | LDLIBS= -llua ${DATA} 12 | test: test.c ${DATA} 13 | 14 | CLEANFILES+= test 15 | 16 | .include 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | luadata 2 | ======= 3 | 4 | Luadata provides C and Lua APIs to handle binary data using Lua scripts. Here is a brief description of those: 5 | 6 | ## 1. Lua API 7 | 8 | ### 1.1 creation 9 | 10 | #### ```data.new(table)``` 11 | 12 | Returns a new data object initialized with the given byte array. For example: 13 | ```Lua 14 | d1 = data.new{0xFF, 0xFE, 0x00} --> returns a data object with 3 bytes. 15 | ``` 16 | 17 | #### ```data.new(number)``` 18 | 19 | Returns a new data object with the size defined by the given argument in bytes. For example: 20 | ```Lua 21 | d2 = data.new(2) --> returns a data object with 2 bytes. 22 | ``` 23 | 24 | #### ```data.new(string)``` 25 | 26 | Returns a new data object initialized with the given string. For example: 27 | ```Lua 28 | d2 = data.new'\a' --> returns a data object with 1 byte. 29 | ``` 30 | 31 | `data.new()` may raise a Lua error. 32 | 33 | ### 1.2 layout 34 | 35 | #### ```data.layout(table)``` 36 | 37 | Returns a new layout table based on table argument, which should have the following formats for its fields: 38 | 39 | 1. ```field = {, [, [,]]}``` or 40 | 2. ```field = {offset = , length = [, endian = , type = ]}``` 41 | 42 | Where, field is the name of the field, \ is the field offset, \ is the field length, 43 | \ is a string that indicates the field type ('number', 'string'), 44 | \ is ia string that indicates the field endianness ('host', 'net', 'little', 'big'). 45 | The default value for type is 'number'. 46 | The default value for endian is 'big'. 47 | 48 | When \ is not 'string', offset and length are in bits (MSB 0). Otherwise, offset and length are in bytes. 49 | 50 | A field lying outside the bounds of the data object is always nil. 51 | 52 | Here are a couple examples: 53 | 54 | * format 1: 55 | 56 | ```Lua 57 | l1 = data.layout{ 58 | msb = {0, 1}, 59 | uint32 = {0, 32}, 60 | uint64le = {0, 64, 'little'}, 61 | str = {0, 3, 'string'} 62 | } 63 | 64 | ``` 65 | 66 | * format 2: 67 | 68 | ```Lua 69 | l2 = data.layout{ 70 | msb = {offset = 0, length = 1}, 71 | net_unaligned_uint16 = {offset = 1, length = 16, endian = 'net'}, 72 | str = {offset = 0, length = 3, endian = 'string'} 73 | } 74 | ``` 75 | 76 | #### ```d:layout(layout | table)``` 77 | 78 | Applies a layout table on a given data object. If a regular table is passed, it calls data.layout(table) first. For example: 79 | 80 | ```Lua 81 | d1:layout(l1) -- applies l1 layout into d1 data object 82 | d2:layout{byte = {0, 8}} -- creates and applies a new layout into d2 data object 83 | ``` 84 | 85 | ### 1.3 segment 86 | 87 | #### ```d:segment([ offset [, length ])``` 88 | 89 | Returns a new data object pointing for the same raw data (memory region) of a given data object, but limited by offset and length parameters. If length is ommited, it assumes that length is the original length minus the offset. If offset is ommited, it assumes the whole data. For example: 90 | ```Lua 91 | d1 = d:segment(0, 2) --> returns a data object with 2 bytes. 92 | d2 = d:segment(2) --> returns a data object with 1 byte. 93 | d3 = d:segment() --> returns a data object with 3 bytes. 94 | ``` 95 | 96 | Note, all the three data objects point to the same raw data of the d data object. 97 | 98 | ## 2. C API 99 | 100 | ### 2.1 creation 101 | 102 | #### ```int ldata_newref(lua_State *L, void *ptr, size_t size);``` 103 | 104 | 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 105 | for it. The data object will not be garbage-collected until it is unreferred. 106 | 107 | This function may raise a Lua error. 108 | 109 | ### 2.2 deletion 110 | 111 | #### ```void ldata_unref(lua_State *L, int ref);``` 112 | 113 | Removes the ptr from the data object and releases the data-object reference, allowing it to be garbage-collected. After that, it is safe 114 | to free the ptr pointer. 115 | 116 | ### 2.3 conversion 117 | 118 | #### ```void * ldata_topointer(lua_State *L, int index, size_t *size);``` 119 | 120 | Returns a pointer for the raw data referenced by the data object at the given index. 121 | If the value at the given index is not a valid data object or the data object is empty (that is, it has no raw data), 122 | then it returns NULL and size will be set with zero. 123 | 124 | Note, similarly to [lua_tolstring](http://www.lua.org/manual/5.1/manual.html#lua_tolstring), 125 | there is no guarantee that the pointer returned by ```ldata_topointer``` will be valid after the corresponding value is removed from the stack. 126 | 127 | 128 | ## 3. Examples 129 | 130 | ### Lua 131 | * [test.lua](https://github.com/lneto/luadata/blob/master/test.lua) 132 | 133 | ### C 134 | * [test.c](https://github.com/lneto/luadata/blob/master/test.c) 135 | * [ctest.lua](https://github.com/lneto/luadata/blob/master/ctest.lua) 136 | -------------------------------------------------------------------------------- /binary.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _KERNEL 29 | #include 30 | #include 31 | #include 32 | #else 33 | #if defined(__NetBSD__) 34 | #include 35 | #include 36 | #elif defined(__linux__) 37 | #include 38 | #endif 39 | #endif 40 | 41 | #include 42 | 43 | #include "binary.h" 44 | 45 | #define BYTE_MAX UCHAR_MAX 46 | #define UINT64_BIT (64) 47 | 48 | inline static void 49 | set_bits(uint64_t *value, uint64_t clear_mask, uint64_t set_mask) 50 | { 51 | *value &= clear_mask; 52 | *value |= set_mask; 53 | } 54 | 55 | #define CONTIGUOUS_BITS(widt, truncated) (width - truncated) 56 | 57 | static void 58 | expand(uint64_t *value, size_t width, size_t msb_offset, byte_t truncated) 59 | { 60 | size_t contiguous = CONTIGUOUS_BITS(width, truncated); 61 | 62 | size_t trunc_msb_offset = BYTE_BIT - truncated; 63 | size_t trunc_lsb_offset = contiguous + trunc_msb_offset; 64 | 65 | size_t clear_offset = msb_offset + truncated; 66 | 67 | uint64_t clear_mask = UINT64_MAX >> clear_offset; 68 | uint64_t trunc_mask = *value >> trunc_lsb_offset << contiguous; 69 | 70 | set_bits(value, clear_mask, trunc_mask); 71 | } 72 | 73 | static void 74 | contract(uint64_t *value, size_t width, size_t msb_offset, byte_t truncated) 75 | { 76 | size_t contiguous = CONTIGUOUS_BITS(width, truncated); 77 | 78 | size_t trunc_lsb_offset = BYTE_BIT - truncated; 79 | size_t trunc_msb_offset = contiguous + trunc_lsb_offset; 80 | 81 | size_t clear_offset = msb_offset + truncated; 82 | 83 | uint64_t clear_mask = UINT64_MAX << clear_offset; 84 | uint64_t trunc_mask = *value << trunc_msb_offset >> contiguous; 85 | 86 | set_bits(value, clear_mask, trunc_mask); 87 | } 88 | 89 | #define TRUNCATED_BITS(width) (width % BYTE_BIT) 90 | 91 | #define VALUE_MSB_OFFSET(width) (UINT64_BIT - width) 92 | 93 | static void 94 | swap_bytes_in(uint64_t *value, size_t width) 95 | { 96 | size_t msb_offset = VALUE_MSB_OFFSET(width); 97 | 98 | *value <<= msb_offset; 99 | 100 | *value = bswap64(*value); 101 | 102 | byte_t truncated = TRUNCATED_BITS(width); 103 | if (truncated > 0) 104 | expand(value, width, msb_offset, truncated); 105 | } 106 | 107 | static void 108 | swap_bytes_out(uint64_t *value, size_t width) 109 | { 110 | size_t msb_offset = VALUE_MSB_OFFSET(width); 111 | 112 | *value = bswap64(*value); 113 | 114 | byte_t truncated = TRUNCATED_BITS(width); 115 | if (truncated > 0) 116 | contract(value, width, msb_offset, truncated); 117 | 118 | *value >>= msb_offset; 119 | } 120 | 121 | #define MSB_OFFSET(offset) (offset % BYTE_BIT) 122 | 123 | #define LSB_OFFSET(width, msb_offset) \ 124 | MAX((ssize_t) (BYTE_BIT - msb_offset - width), (ssize_t) 0) 125 | 126 | #define BYTE_POSITION(offset) (offset / BYTE_BIT) 127 | 128 | #define OVERFLOW_BITS(width, msb_offset, lsb_offset) \ 129 | (width - (BYTE_BIT - msb_offset - lsb_offset)) 130 | 131 | #define MASK(msb_offset, lsb_offset) \ 132 | ((byte_t) BYTE_MAX >> (msb_offset + lsb_offset) << lsb_offset) 133 | 134 | #define OVERFLOW_LSB_OFFSET(overflow) (BYTE_BIT - overflow) 135 | 136 | #define NEED_SWAP(width, endian) \ 137 | (width > BYTE_BIT && endian == LITTLE_ENDIAN) 138 | 139 | uint64_t 140 | binary_get_uint64(byte_t *bytes, size_t offset, size_t width, int endian) 141 | { 142 | size_t msb_offset = MSB_OFFSET(offset); 143 | size_t lsb_offset = LSB_OFFSET(width, msb_offset); 144 | size_t pos = BYTE_POSITION(offset); 145 | size_t overflow = OVERFLOW_BITS(width, msb_offset, lsb_offset); 146 | byte_t mask = MASK(msb_offset, lsb_offset); 147 | 148 | uint64_t value = (byte_t) (bytes[ pos ] & mask) >> lsb_offset; 149 | 150 | for (; overflow >= BYTE_BIT; overflow -= BYTE_BIT) 151 | value = (value << BYTE_BIT) | bytes[ ++pos ]; 152 | 153 | if (overflow > 0) { 154 | /* assertion: overflow < BYTE_BIT */ 155 | size_t overflow_lsb_offset = OVERFLOW_LSB_OFFSET(overflow); 156 | 157 | value <<= overflow; 158 | value |= (byte_t) bytes[ ++pos ] >> overflow_lsb_offset; 159 | } 160 | 161 | if (NEED_SWAP(width, endian)) 162 | swap_bytes_in(&value, width); 163 | 164 | return value; 165 | } 166 | 167 | void 168 | binary_set_uint64(byte_t *bytes, size_t offset, size_t width, int endian, 169 | uint64_t value) 170 | { 171 | size_t msb_offset = MSB_OFFSET(offset); 172 | size_t lsb_offset = LSB_OFFSET(width, msb_offset); 173 | size_t pos = BYTE_POSITION(offset); 174 | size_t overflow = OVERFLOW_BITS(width, msb_offset, lsb_offset); 175 | byte_t clear_mask = ~MASK(msb_offset, lsb_offset); 176 | 177 | if (NEED_SWAP(width, endian)) 178 | swap_bytes_out(&value, width); 179 | 180 | bytes[ pos ] &= clear_mask; 181 | bytes[ pos ] |= (uint64_t) value << lsb_offset >> overflow; 182 | 183 | for (; overflow >= BYTE_BIT; overflow -= BYTE_BIT) 184 | bytes[ ++pos ] = (uint64_t) value >> (overflow - BYTE_BIT); 185 | 186 | if (overflow > 0) { 187 | /* assertion: overflow < BYTE_BIT */ 188 | size_t overflow_lsb_offset = OVERFLOW_LSB_OFFSET(overflow); 189 | byte_t overflow_clear_mask = ~(BYTE_MAX << overflow_lsb_offset); 190 | 191 | bytes[ ++pos ] &= overflow_clear_mask; 192 | bytes[ pos ] |= value << overflow_lsb_offset; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /binary.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _BINARY_H_ 29 | #define _BINARY_H_ 30 | 31 | #include 32 | 33 | #ifndef _KERNEL 34 | #include 35 | #include 36 | #else 37 | #if defined(__NetBSD__) 38 | #include 39 | #elif defined(__linux__) 40 | #include 41 | #endif 42 | #endif 43 | 44 | #define BYTE_BIT CHAR_BIT 45 | 46 | typedef unsigned char byte_t; 47 | 48 | uint64_t binary_get_uint64(byte_t *, size_t, size_t, int); 49 | 50 | void binary_set_uint64(byte_t *, size_t, size_t, int, uint64_t); 51 | 52 | #define CEIL_DIV(x, y) ((x + y - 1) / y) 53 | #define BIT_TO_BYTE(x) (CEIL_DIV(x, BYTE_BIT)) 54 | #define BYTE_TO_BIT(x) (x * BYTE_BIT) 55 | 56 | #endif /* _BINARY_H_ */ 57 | -------------------------------------------------------------------------------- /ctest.lua: -------------------------------------------------------------------------------- 1 | function filter(d) 2 | -- store d in a global 3 | gd = d 4 | d:layout{ 5 | -- most significant 4-bits 6 | uint4_msb = {0,4}, 7 | -- inner 16-bits 8 | uint16 = {4, 16}, 9 | -- least significant 4-bits 10 | uint4_lsb = {20, 4} 11 | } 12 | return d.uint4_msb == 0xa and 13 | d.uint16 == 0xbcde and 14 | d.uint4_lsb == 0xf 15 | end 16 | 17 | function access_global() 18 | -- should return nil if ldata_unref(d) has been called from C 19 | return gd.uint16 20 | end 21 | 22 | d = data.new{0xff, 0xee, 0xdd, 0x00} 23 | -------------------------------------------------------------------------------- /data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _KERNEL 29 | #include 30 | #include 31 | #else 32 | #if defined(__NetBSD__) 33 | #include 34 | #include 35 | #endif 36 | #endif 37 | 38 | #include 39 | 40 | #include "luautil.h" 41 | 42 | #include "data.h" 43 | #include "binary.h" 44 | #include "layout.h" 45 | 46 | #define LUA_INTEGER_BYTE (sizeof(lua_Integer)) 47 | #define LUA_INTEGER_BIT (LUA_INTEGER_BYTE * BYTE_BIT) 48 | 49 | inline static bool 50 | check_offset(data_t *data, size_t offset, size_t length) 51 | { 52 | size_t last_pos = data->offset + data->length - 1; 53 | return offset >= data->offset && offset <= last_pos; 54 | } 55 | 56 | inline static bool 57 | check_length(data_t *data, size_t offset, size_t length) 58 | { 59 | return offset + length <= data->offset + data->length; 60 | } 61 | 62 | inline static bool 63 | check_limits(data_t *data, size_t offset, size_t length) 64 | { 65 | return check_offset(data, offset, length) && 66 | check_length(data, offset, length); 67 | } 68 | 69 | #define ENTRY_BYTE_OFFSET(data, entry) \ 70 | ((BIT_TO_BYTE(entry->offset + 1) - 1) + data->offset) 71 | 72 | inline static bool 73 | check_num_limits(data_t *data, layout_entry_t *entry) 74 | { 75 | size_t offset = ENTRY_BYTE_OFFSET(data, entry); 76 | size_t length = BIT_TO_BYTE(entry->length); 77 | 78 | return entry->length <= LUA_INTEGER_BIT && 79 | check_limits(data, offset, length); 80 | } 81 | 82 | inline static bool 83 | check_str_limits(data_t *data, layout_entry_t *entry) 84 | { 85 | size_t offset = entry->offset + data->offset; 86 | size_t length = entry->length; 87 | return check_limits(data, offset, length); 88 | } 89 | 90 | inline static layout_entry_t * 91 | get_entry(lua_State *L, data_t *data, int key_ix) 92 | { 93 | if (!luau_isvalidref(data->layout)) 94 | return NULL; 95 | 96 | return layout_get_entry(L, data->layout, key_ix); 97 | } 98 | 99 | static data_t * 100 | new_data(lua_State *L, handle_t *handle, size_t offset, size_t length) 101 | { 102 | data_t *data = lua_newuserdata(L, sizeof(data_t)); 103 | 104 | data->handle = handle; 105 | data->offset = offset; 106 | data->length = length; 107 | data->layout = LUA_REFNIL; 108 | 109 | luau_setmetatable(L, DATA_USERDATA); 110 | 111 | return data; 112 | } 113 | 114 | #define BINARY_PARMS(data, entry, ptr) \ 115 | ptr, entry->offset, entry->length, entry->endian 116 | 117 | inline static int 118 | get_num(lua_State *L, data_t *data, layout_entry_t *entry) 119 | { 120 | if (!check_num_limits(data, entry)) 121 | return 0; 122 | 123 | byte_t *ptr = (byte_t *) data_get_ptr(data); 124 | if (ptr == NULL) 125 | return 0; 126 | 127 | /* assertion: LUA_INTEGER_BIT <= 64 */ 128 | lua_Integer value = binary_get_uint64(BINARY_PARMS(data, entry, ptr)); 129 | lua_pushinteger(L, value); 130 | return 1; 131 | } 132 | 133 | inline static int 134 | get_str(lua_State *L, data_t *data, layout_entry_t *entry) 135 | { 136 | if (!check_str_limits(data, entry)) 137 | return 0; 138 | 139 | const char *ptr = (const char *) data_get_ptr(data); 140 | const char *s = ptr + entry->offset; 141 | lua_pushlstring(L, s, entry->length); 142 | return 1; 143 | } 144 | 145 | inline static void 146 | set_num(lua_State *L, data_t *data, layout_entry_t *entry, int value_ix) 147 | { 148 | if (!check_num_limits(data, entry)) 149 | return; 150 | 151 | byte_t *ptr = (byte_t *) data_get_ptr(data); 152 | if (ptr == NULL) 153 | return; 154 | 155 | /* assertion: LUA_INTEGER_BIT <= 64 */ 156 | lua_Integer value = lua_tointeger(L, value_ix); 157 | binary_set_uint64(BINARY_PARMS(data, entry, ptr), value); 158 | } 159 | 160 | static void 161 | set_str(lua_State *L, data_t *data, layout_entry_t *entry, int value_ix) 162 | { 163 | if (!check_str_limits(data, entry)) 164 | return; 165 | 166 | size_t len; 167 | const char *s = lua_tolstring(L, value_ix, &len); 168 | if (s == NULL) 169 | return; 170 | 171 | char *ptr = (char *) data_get_ptr(data); 172 | memcpy(ptr + entry->offset, s, MIN(len, entry->length)); 173 | } 174 | 175 | inline data_t * 176 | data_new(lua_State *L, void *ptr, size_t size, bool free) 177 | { 178 | handle_t *handle = handle_new_single(L, ptr, size, free); 179 | if (handle == NULL) 180 | luaL_error(L, "not enough memory"); 181 | 182 | data_t *data = new_data(L, handle, 0, size); 183 | return data; 184 | } 185 | 186 | #if defined(_KERNEL) && defined(__NetBSD__) 187 | inline data_t * 188 | data_new_chain(lua_State *L, struct mbuf *chain, bool free) 189 | { 190 | handle_t *handle = handle_new_chain(L, chain, free); 191 | if (handle == NULL) 192 | return luaL_error(L, "not enough memory"); 193 | 194 | data_t *data = new_data(L, handle, 0, chain->m_len); 195 | return data; 196 | } 197 | #endif 198 | 199 | int 200 | data_new_segment(lua_State *L, data_t *data, size_t offset, size_t length) 201 | { 202 | if (!check_limits(data, offset, length)) 203 | return 0; 204 | 205 | handle_t *handle = data->handle; 206 | 207 | handle->refcount++; 208 | 209 | new_data(L, handle, offset, length); 210 | return 1; 211 | } 212 | 213 | inline void 214 | data_delete(lua_State *L, data_t *data) 215 | { 216 | handle_delete(L, data->handle); 217 | 218 | if (luau_isvalidref(data->layout)) 219 | luau_unref(L, data->layout); 220 | } 221 | 222 | inline data_t * 223 | data_test(lua_State *L, int index) 224 | { 225 | #if LUA_VERSION_NUM >= 502 226 | return (data_t *) luaL_testudata(L, index, DATA_USERDATA); 227 | #else 228 | return (data_t *) luaL_checkudata(L, index, DATA_USERDATA); 229 | #endif 230 | } 231 | 232 | inline void 233 | data_apply_layout(lua_State *L, data_t *data, int layout_ix) 234 | { 235 | luau_unref(L, data->layout); 236 | lua_pushvalue(L, layout_ix); 237 | data->layout = luau_ref(L); 238 | } 239 | 240 | int 241 | data_get_field(lua_State *L, data_t *data, int key_ix) 242 | { 243 | layout_entry_t *entry = get_entry(L, data, key_ix); 244 | if (entry == NULL) 245 | return 0; 246 | 247 | switch (entry->type) { 248 | case LAYOUT_TNUMBER: 249 | return get_num(L, data, entry); 250 | case LAYOUT_TSTRING: 251 | return get_str(L, data, entry); 252 | } 253 | return 0; /* unreached */ 254 | } 255 | 256 | void 257 | data_set_field(lua_State *L, data_t *data, int key_ix, int value_ix) 258 | { 259 | layout_entry_t *entry = get_entry(L, data, key_ix); 260 | if (entry == NULL) 261 | return; 262 | 263 | switch (entry->type) { 264 | case LAYOUT_TNUMBER: 265 | set_num(L, data, entry, value_ix); 266 | break; 267 | case LAYOUT_TSTRING: 268 | set_str(L, data, entry, value_ix); 269 | break; 270 | } 271 | } 272 | 273 | inline void * 274 | data_get_ptr(data_t *data) 275 | { 276 | return handle_get_ptr(data->handle, data->offset, data->length); 277 | } 278 | 279 | inline void 280 | data_unref(data_t *data) 281 | { 282 | handle_unref(data->handle); 283 | } 284 | 285 | -------------------------------------------------------------------------------- /data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _DATA_H_ 29 | #define _DATA_H_ 30 | 31 | #ifndef _KERNEL 32 | #include 33 | #include 34 | #else 35 | #if defined(__NetBSD__) 36 | #include 37 | #include 38 | #endif 39 | #endif 40 | 41 | #include 42 | 43 | #include "handle.h" 44 | #include "layout.h" 45 | 46 | #define DATA_LIB "data" 47 | #define DATA_USERDATA "data.data" 48 | 49 | typedef struct { 50 | handle_t *handle; 51 | size_t offset; 52 | size_t length; 53 | int layout; 54 | } data_t; 55 | 56 | data_t * data_new(lua_State *, void *, size_t, bool); 57 | 58 | #if defined(_KERNEL) && defined(__NetBSD__) 59 | data_t * data_new_chain(lua_State *, struct mbuf *, bool); 60 | #endif 61 | 62 | int data_new_segment(lua_State *, data_t *, size_t, size_t); 63 | 64 | void data_delete(lua_State *, data_t *); 65 | 66 | data_t * data_test(lua_State *, int); 67 | 68 | void data_apply_layout(lua_State *, data_t *, int); 69 | 70 | int data_get_field(lua_State *, data_t *, int); 71 | 72 | void data_set_field(lua_State *, data_t *, int, int); 73 | 74 | void * data_get_ptr(data_t *); 75 | 76 | void data_unref(data_t *); 77 | 78 | #endif /* _DATA_H_ */ 79 | -------------------------------------------------------------------------------- /handle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifdef _KERNEL 29 | #if defined(__NetBSD__) 30 | #include 31 | #elif defined(__linux__) 32 | #include 33 | #endif 34 | #endif 35 | 36 | #include 37 | 38 | #include "luautil.h" 39 | 40 | #include "handle.h" 41 | 42 | static void 43 | free_handle(lua_State *L, handle_t *handle) 44 | { 45 | switch (handle->type) { 46 | case HANDLE_TYPE_SINGLE: 47 | { 48 | single_t *single = &handle->bucket.single; 49 | luau_free(L, single->ptr, single->size); 50 | break; 51 | } 52 | case HANDLE_TYPE_CHAIN: 53 | { 54 | #if defined(_KERNEL) && defined(__NetBSD__) 55 | struct mbuf *chain = handle->bucket.chain; 56 | m_free(chain); 57 | #endif 58 | break; 59 | } 60 | } 61 | } 62 | 63 | handle_t * 64 | handle_new_single(lua_State *L, void *ptr, size_t size, bool free) 65 | { 66 | handle_t *handle = (handle_t *) luau_malloc(L, sizeof(handle_t)); 67 | 68 | if (handle == NULL) 69 | return NULL; 70 | 71 | single_t *single = &handle->bucket.single; 72 | single->ptr = ptr; 73 | single->size = size; 74 | 75 | handle->type = HANDLE_TYPE_SINGLE; 76 | handle->refcount = 0; 77 | handle->free = free; 78 | 79 | return handle; 80 | } 81 | 82 | #if defined(_KERNEL) && defined(__NetBSD__) 83 | handle_t * 84 | handle_new_chain(lua_State *L, struct mbuf *chain, bool free) 85 | { 86 | handle_t *handle = (handle_t *) luau_malloc(L, sizeof(handle_t)); 87 | 88 | if (handle == NULL) 89 | return NULL; 90 | 91 | handle->bucket.chain = chain; 92 | 93 | handle->type = HANDLE_TYPE_CHAIN; 94 | handle->refcount = 0; 95 | handle->free = free; 96 | 97 | return handle; 98 | } 99 | #endif 100 | 101 | void 102 | handle_delete(lua_State *L, handle_t *handle) 103 | { 104 | if (handle->refcount == 0) { 105 | if (handle->free) 106 | free_handle(L, handle); 107 | 108 | luau_free(L, handle, sizeof(handle_t)); 109 | } 110 | else 111 | handle->refcount--; 112 | } 113 | 114 | void * 115 | handle_get_ptr(handle_t *handle, size_t offset, size_t length) 116 | { 117 | void *ptr = NULL; 118 | 119 | switch (handle->type) { 120 | case HANDLE_TYPE_SINGLE: 121 | { 122 | single_t *single = &handle->bucket.single; 123 | if (single->ptr == NULL) 124 | return NULL; 125 | 126 | ptr = (char *) single->ptr + offset; 127 | break; 128 | } 129 | case HANDLE_TYPE_CHAIN: 130 | { 131 | #if defined(_KERNEL) && defined(__NetBSD__) 132 | struct mbuf *chain = handle->bucket.chain; 133 | if (chain == NULL || offset > INT_MAX || length > INT_MAX) 134 | return NULL; 135 | 136 | struct mbuf *m = m_pulldown(chain, (int) offset, (int) length, 137 | NULL); 138 | if (m == NULL) 139 | return NULL; 140 | 141 | ptr = mtod(m, void *); 142 | #endif 143 | } 144 | } 145 | 146 | return ptr; 147 | } 148 | 149 | void 150 | handle_unref(handle_t *handle) 151 | { 152 | switch (handle->type) { 153 | case HANDLE_TYPE_SINGLE: 154 | { 155 | single_t *single = &handle->bucket.single; 156 | single->ptr = NULL; 157 | single->size = 0; 158 | break; 159 | } 160 | case HANDLE_TYPE_CHAIN: 161 | { 162 | #if defined(_KERNEL) && defined(__NetBSD__) 163 | handle->bucket.chain = NULL; 164 | #endif 165 | break; 166 | } 167 | } 168 | } 169 | 170 | -------------------------------------------------------------------------------- /handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _HANDLE_H_ 29 | #define _HANDLE_H_ 30 | 31 | #ifndef _KERNEL 32 | #include 33 | #include 34 | #else 35 | #if defined(__NetBSD__) 36 | #include 37 | #include 38 | #endif 39 | #endif 40 | 41 | #include 42 | 43 | typedef struct { 44 | void *ptr; 45 | size_t size; 46 | } single_t; 47 | 48 | typedef union { 49 | single_t single; 50 | #if defined(_KERNEL) && defined(__NetBSD__) 51 | struct mbuf *chain; 52 | #endif 53 | } bucket_t; 54 | 55 | typedef enum { 56 | HANDLE_TYPE_SINGLE = 0, 57 | HANDLE_TYPE_CHAIN, 58 | } handle_type_t; 59 | 60 | typedef struct { 61 | bucket_t bucket; 62 | handle_type_t type; 63 | size_t refcount; 64 | bool free; 65 | } handle_t; 66 | 67 | handle_t * handle_new_single(lua_State *, void *, size_t, bool); 68 | 69 | #if defined(_KERNEL) && defined(__NetBSD__) 70 | handle_t * handle_new_chain(lua_State *, struct mbuf *, bool); 71 | #endif 72 | 73 | void handle_delete(lua_State *, handle_t *); 74 | 75 | void * handle_get_ptr(handle_t *, size_t, size_t); 76 | 77 | void handle_unref(handle_t *); 78 | 79 | #endif /* _HANDLE_H_ */ 80 | -------------------------------------------------------------------------------- /layout.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #include 29 | #include 30 | 31 | #include "luautil.h" 32 | 33 | #include "layout.h" 34 | 35 | inline static layout_entry_t * 36 | test_entry(lua_State *L, int index) 37 | { 38 | #if LUA_VERSION_NUM >= 502 39 | return (layout_entry_t *) 40 | luaL_testudata(L, index, LAYOUT_ENTRY_USERDATA); 41 | #else 42 | return (layout_entry_t *) 43 | luaL_checkudata(L, index, LAYOUT_ENTRY_USERDATA); 44 | #endif 45 | } 46 | 47 | inline static void 48 | init_layout(layout_entry_t *entry) 49 | { 50 | entry->offset = 0; 51 | entry->length = 0; 52 | entry->type = LAYOUT_TYPE_DEFAULT; 53 | entry->endian = LAYOUT_ENDIAN_DEFAULT; 54 | } 55 | 56 | static void 57 | load_type(lua_State *L, layout_entry_t *entry) 58 | { 59 | const char *type = lua_tostring(L, -1); 60 | 61 | if (type[0] == 'n') 62 | entry->type = LAYOUT_TNUMBER; 63 | else if (type[0] == 's') 64 | entry->type = LAYOUT_TSTRING; 65 | } 66 | 67 | static void 68 | load_endian(lua_State *L, layout_entry_t *entry) 69 | { 70 | const char *endian = lua_tostring(L, -1); 71 | 72 | if (endian[0] == 'n' || endian[0] == 'b') 73 | entry->endian = BIG_ENDIAN; 74 | else if (endian[0] == 'l') 75 | entry->endian = LITTLE_ENDIAN; 76 | else if (endian[0] == 'h') 77 | entry->endian = BYTE_ORDER; 78 | } 79 | 80 | static void 81 | load_entry_numbered(lua_State *L, layout_entry_t *entry) 82 | { 83 | #if LUA_VERSION_NUM >= 502 84 | size_t array_len = lua_rawlen(L, -1); 85 | #else 86 | size_t array_len = lua_objlen(L, -1); 87 | #endif 88 | 89 | if (array_len >= 1) 90 | entry->offset = luau_getarray_integer(L, -1, 1); 91 | if (array_len >= 2) 92 | entry->length = luau_getarray_integer(L, -1, 2); 93 | if (array_len >= 3) { 94 | luau_getarray(L, -1, 3); 95 | load_type(L, entry); 96 | lua_pop(L, 1); 97 | } 98 | if (array_len >= 4) { 99 | luau_getarray(L, -1, 4); 100 | load_endian(L, entry); 101 | lua_pop(L, 1); 102 | } 103 | } 104 | 105 | static void 106 | load_entry_named(lua_State *L, layout_entry_t *entry) 107 | { 108 | lua_getfield(L, -1, "offset"); 109 | if (lua_isnumber(L, -1)) 110 | entry->offset = lua_tointeger(L, -1); 111 | lua_pop(L, 1); 112 | 113 | lua_getfield(L, -1, "length"); 114 | if (lua_isnumber(L, -1)) 115 | entry->length = lua_tointeger(L, -1); 116 | lua_pop(L, 1); 117 | 118 | lua_getfield(L, -1, "type"); 119 | if (lua_isstring(L, -1)) 120 | load_type(L, entry); 121 | lua_pop(L, 1); 122 | 123 | lua_getfield(L, -1, "endian"); 124 | if (lua_isstring(L, -1)) 125 | load_endian(L, entry); 126 | lua_pop(L, 1); 127 | } 128 | 129 | static void 130 | load_entry(lua_State *L, layout_entry_t *entry) 131 | { 132 | init_layout(entry); 133 | load_entry_numbered(L, entry); 134 | load_entry_named(L, entry); 135 | } 136 | 137 | static void 138 | copy_entry(layout_entry_t *dst, layout_entry_t *src) 139 | { 140 | dst->offset = src->offset; 141 | dst->length = src->length; 142 | dst->type = src->type; 143 | dst->endian = src->endian; 144 | } 145 | 146 | static int 147 | new_entry(lua_State *L, layout_entry_t *entry) 148 | { 149 | layout_entry_t *nentry = 150 | (layout_entry_t *) lua_newuserdata(L, sizeof(layout_entry_t)); 151 | 152 | luau_setmetatable(L, LAYOUT_ENTRY_USERDATA); 153 | 154 | copy_entry(nentry, entry); 155 | return 1; 156 | } 157 | 158 | void 159 | layout_load(lua_State *L, int index) 160 | { 161 | layout_entry_t entry; 162 | 163 | lua_pushnil(L); /* first key */ 164 | while (lua_next(L, index) != 0) { 165 | /* uses 'key' (at index -2) and 'value' (at index -1) */ 166 | load_entry(L, &entry); 167 | if (entry.length == 0) 168 | lua_pushnil(L); 169 | else 170 | new_entry(L, &entry); 171 | 172 | /* layout[ key ] = entry */ 173 | luau_settable(L, index, -3, -1); 174 | 175 | /* removes 'value' and 'entry'; keeps 'key' for next iteration */ 176 | lua_pop(L, 2); 177 | } 178 | 179 | lua_pushboolean(L, true); 180 | lua_setfield(L, index, LAYOUT_STAMP); 181 | } 182 | 183 | layout_entry_t * 184 | layout_get_entry(lua_State *L, int layout_ix, int key_ix) 185 | { 186 | void *entry = NULL; 187 | 188 | luau_getref(L, layout_ix); 189 | luau_gettable(L, -1, key_ix); 190 | if (lua_isnil(L, -1)) 191 | goto end; 192 | 193 | entry = test_entry(L, -1); 194 | 195 | end: 196 | lua_pop(L, 2); 197 | return entry; 198 | } 199 | 200 | -------------------------------------------------------------------------------- /layout.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _LAYOUT_H_ 29 | #define _LAYOUT_H_ 30 | 31 | #ifndef _KERNEL 32 | #include 33 | #include 34 | #else 35 | #if defined(__NetBSD__) 36 | #include 37 | #endif 38 | #endif 39 | 40 | #include 41 | 42 | #include 43 | 44 | #define LAYOUT_ENTRY_USERDATA "data.layout.entry" 45 | 46 | #define LAYOUT_STAMP "__layout_stamp" 47 | 48 | #define LAYOUT_TYPE_DEFAULT LAYOUT_TNUMBER 49 | #define LAYOUT_ENDIAN_DEFAULT BIG_ENDIAN 50 | 51 | typedef enum { 52 | LAYOUT_TNUMBER = 0, 53 | LAYOUT_TSTRING 54 | } layout_type_t; 55 | 56 | typedef struct { 57 | size_t offset; 58 | size_t length; 59 | layout_type_t type; 60 | int endian; 61 | } layout_entry_t; 62 | 63 | void layout_load(lua_State *, int); 64 | 65 | layout_entry_t * layout_get_entry(lua_State *, int, int); 66 | 67 | #endif /* _LAYOUT_H_ */ 68 | -------------------------------------------------------------------------------- /luadata.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014 Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _KERNEL 29 | #include 30 | #else 31 | #if defined(__NetBSD__) 32 | #include 33 | #elif defined(__linux__) 34 | #include 35 | #endif 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | #include "luautil.h" 42 | 43 | #include "luadata.h" 44 | #include "data.h" 45 | #include "layout.h" 46 | 47 | static char * 48 | new_data_num(lua_State *L, size_t *len) 49 | { 50 | *len = luau_tosize(L, 1); 51 | if (*len == 0) 52 | return NULL; 53 | 54 | char *data = (char *) luau_malloc(L, *len); 55 | if (data == NULL) 56 | return NULL; 57 | 58 | memset(data, 0, *len); 59 | return data; 60 | } 61 | 62 | static char * 63 | new_data_tab(lua_State *L, size_t *len) 64 | { 65 | #if LUA_VERSION_NUM >= 502 66 | *len = lua_rawlen(L, 1); 67 | #else 68 | *len = lua_objlen(L, 1); 69 | #endif 70 | if (*len == 0) 71 | return NULL; 72 | 73 | char *data = (char *) luau_malloc(L, *len); 74 | if (data == NULL) 75 | return NULL; 76 | 77 | size_t i = 0; 78 | lua_pushnil(L); /* first key */ 79 | while (lua_next(L, 1) != 0 && i < *len) { 80 | /* uses 'key' (at index -2) and 'value' (at index -1) */ 81 | data[ i++ ] = (char) lua_tointeger(L, -1); 82 | /* removes 'value'; keeps 'key' for next iteration */ 83 | lua_pop(L, 1); 84 | } 85 | return data; 86 | } 87 | 88 | static char * 89 | new_data_str(lua_State *L, size_t *len) 90 | { 91 | const char *str = lua_tolstring(L, 1, len); 92 | if (str == NULL || *len == 0) 93 | return NULL; 94 | 95 | char *data = (char *) luau_malloc(L, *len); 96 | if (data == NULL) 97 | return NULL; 98 | 99 | memcpy(data, str, *len); 100 | return data; 101 | } 102 | 103 | static int 104 | new_data(lua_State *L) 105 | { 106 | char *data = NULL; 107 | size_t len = 0; 108 | 109 | int type = lua_type(L, 1); 110 | if (type == LUA_TNUMBER) 111 | data = new_data_num(L, &len); 112 | else if (type == LUA_TTABLE) 113 | data = new_data_tab(L, &len); 114 | else if (type == LUA_TSTRING) 115 | data = new_data_str(L, &len); 116 | 117 | if (data == NULL || len == 0) 118 | return 0; 119 | 120 | data_new(L, (void *) data, len, true); 121 | return 1; 122 | } 123 | 124 | static int 125 | new_layout(lua_State *L) 126 | { 127 | if (!lua_istable(L, 1)) 128 | return 0; 129 | 130 | layout_load(L, 1); 131 | return 1; 132 | } 133 | 134 | static int 135 | new_segment(lua_State *L) 136 | { 137 | data_t *data = lua_touserdata(L, 1); 138 | 139 | size_t offset = data->offset; 140 | size_t length = data->length; 141 | 142 | int nargs = lua_gettop(L); 143 | if (nargs >= 2) { 144 | size_t seg_offset = luau_tosize(L, 2); 145 | 146 | offset += seg_offset; 147 | 148 | if (nargs >= 3) 149 | length = luau_tosize(L, 3); 150 | else 151 | length -= seg_offset; 152 | } 153 | 154 | return data_new_segment(L, data, offset, length); 155 | } 156 | 157 | static int 158 | apply_layout(lua_State *L) 159 | { 160 | data_t *data = lua_touserdata(L, 1); 161 | 162 | if (!lua_istable(L, 2)) 163 | return 0; 164 | 165 | lua_getfield(L, 2, LAYOUT_STAMP); 166 | bool is_layout = (bool) lua_toboolean(L, -1); 167 | lua_pop(L, 1); 168 | 169 | if (!is_layout) 170 | layout_load(L, 2); 171 | 172 | data_apply_layout(L, data, 2); 173 | 174 | /* return data object */ 175 | lua_pushvalue(L, 1); 176 | return 1; 177 | } 178 | 179 | static int 180 | __gc(lua_State *L) 181 | { 182 | data_t *data = lua_touserdata(L, 1); 183 | data_delete(L, data); 184 | return 0; 185 | } 186 | 187 | static int 188 | __index(lua_State *L) 189 | { 190 | data_t *data = lua_touserdata(L, 1); 191 | 192 | /* try object-oriented access first */ 193 | luau_getmetatable(L, 1, 2); 194 | if (!lua_isnil(L, -1)) 195 | /* return this method */ 196 | return 1; 197 | 198 | lua_pop(L, 1); 199 | return data_get_field(L, data, 2); 200 | } 201 | 202 | static int 203 | __newindex(lua_State *L) 204 | { 205 | data_t *data = lua_touserdata(L, 1); 206 | 207 | /* try object-oriented access first */ 208 | luau_getmetatable(L, 1, 2); 209 | if (!lua_isnil(L, -1)) 210 | /* shouldn't overwrite a method */ 211 | goto end; 212 | 213 | data_set_field(L, data, 2, 3); 214 | end: 215 | lua_pop(L, 1); 216 | return 0; 217 | } 218 | 219 | inline static int 220 | __len(lua_State *L) 221 | { 222 | data_t *data = lua_touserdata(L, 1); 223 | 224 | luau_pushsize(L, data->length); 225 | return 1; 226 | } 227 | 228 | inline static int 229 | __tostring(lua_State *L) 230 | { 231 | data_t *data = lua_touserdata(L, 1); 232 | 233 | const char * ptr = (const char *) data_get_ptr(data); 234 | lua_pushlstring(L, ptr, data->length); 235 | return 1; 236 | } 237 | 238 | static const luaL_Reg data_lib[ ] = { 239 | {"new" , new_data}, 240 | {"layout", new_layout}, 241 | {NULL , NULL} 242 | }; 243 | 244 | static const luaL_Reg data_m[ ] = { 245 | {"layout" , apply_layout}, 246 | {"segment" , new_segment}, 247 | {"__index" , __index}, 248 | {"__newindex", __newindex}, 249 | {"__gc" , __gc}, 250 | {"__len" , __len}, 251 | {"__tostring", __tostring}, 252 | {NULL , NULL} 253 | }; 254 | 255 | static const luaL_Reg layout_entry_m[ ] = { 256 | {NULL, NULL} 257 | }; 258 | 259 | int 260 | luaopen_data(lua_State *L) 261 | { 262 | luaL_newmetatable(L, LAYOUT_ENTRY_USERDATA); 263 | #if LUA_VERSION_NUM >= 502 264 | luaL_setfuncs(L, layout_entry_m, 0); 265 | #else 266 | luaL_register(L, NULL, layout_entry_m); 267 | #endif 268 | lua_pop(L, 1); 269 | 270 | luaL_newmetatable(L, DATA_USERDATA); 271 | #if LUA_VERSION_NUM >= 502 272 | luaL_setfuncs(L, data_m, 0); 273 | luaL_newlib(L, data_lib); 274 | #else 275 | luaL_register(L, NULL, data_m); 276 | luaL_register(L, DATA_LIB, data_lib); 277 | #endif 278 | 279 | return 1; 280 | } 281 | 282 | int 283 | ldata_newref(lua_State *L, void *ptr, size_t size) 284 | { 285 | data_new(L, ptr, size, false); 286 | /* keep the new data object on the stack */ 287 | lua_pushvalue(L, -1); 288 | return luau_ref(L); 289 | } 290 | 291 | #if defined(_KERNEL) && defined(__NetBSD__) 292 | int 293 | ldata_newref_chain(lua_State *L, struct mbuf *chain) 294 | { 295 | data_new_chain(L, chain, false); 296 | /* keep the new data object on the stack */ 297 | lua_pushvalue(L, -1); 298 | return luau_ref(L); 299 | } 300 | #endif 301 | 302 | void 303 | ldata_unref(lua_State *L, int r) 304 | { 305 | luau_getref(L, r); 306 | 307 | data_t *data = data_test(L, -1); 308 | if (data == NULL) { 309 | lua_pop(L, 1); 310 | return; 311 | } 312 | 313 | data_unref(data); 314 | 315 | /* pop data object */ 316 | lua_pop(L, 1); 317 | luau_unref(L, r); 318 | } 319 | 320 | void * 321 | ldata_topointer(lua_State *L, int index, size_t *size) 322 | { 323 | data_t *data = data_test(L, index); 324 | if (data == NULL) { 325 | if (size != NULL) 326 | *size = 0; 327 | return NULL; 328 | } 329 | 330 | if (size != NULL) 331 | *size = data->length; 332 | 333 | return data_get_ptr(data); 334 | } 335 | 336 | #if defined(_KERNEL) && defined(_MODULE) 337 | #if defined(__NetBSD__) 338 | #include 339 | #include 340 | 341 | MODULE(MODULE_CLASS_MISC, luadata, "lua"); 342 | 343 | static int 344 | luadata_modcmd(modcmd_t cmd, void *opaque) 345 | { 346 | int error; 347 | 348 | switch (cmd) { 349 | case MODULE_CMD_INIT: 350 | error = klua_mod_register(DATA_LIB, luaopen_data); 351 | break; 352 | case MODULE_CMD_FINI: 353 | error = klua_mod_unregister(DATA_LIB); 354 | break; 355 | default: 356 | error = ENOTTY; 357 | } 358 | return error; 359 | } 360 | #elif defined(__linux__) 361 | #include 362 | 363 | EXPORT_SYMBOL(luaopen_data); 364 | EXPORT_SYMBOL(ldata_newref); 365 | EXPORT_SYMBOL(ldata_unref); 366 | EXPORT_SYMBOL(ldata_topointer); 367 | 368 | static int __init data_init(void) 369 | { 370 | return 0; 371 | } 372 | 373 | static void __exit data_exit(void) 374 | { 375 | } 376 | 377 | module_init(data_init); 378 | module_exit(data_exit); 379 | MODULE_LICENSE("Dual MIT/GPL"); 380 | #endif 381 | #endif 382 | -------------------------------------------------------------------------------- /luadata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _LUA_DATA_H_ 29 | #define _LUA_DATA_H_ 30 | 31 | #ifndef _KERNEL 32 | #include 33 | #else 34 | #if defined(__NetBSD__) 35 | #include 36 | #include 37 | #elif defined(__linux__) 38 | #include 39 | #endif 40 | #endif 41 | 42 | #include 43 | 44 | extern int luaopen_data(lua_State *); 45 | 46 | extern int ldata_newref(lua_State *, void *, size_t); 47 | 48 | #if defined(_KERNEL) && defined(__NetBSD__) 49 | extern int ldata_newref_chain(lua_State *, struct mbuf *); 50 | #endif 51 | 52 | extern void ldata_unref(lua_State *, int); 53 | 54 | extern void * ldata_topointer(lua_State *, int, size_t *); 55 | 56 | #endif /* _LUA_DATA_H_ */ 57 | -------------------------------------------------------------------------------- /luadata_core.c: -------------------------------------------------------------------------------- 1 | luadata.c -------------------------------------------------------------------------------- /luautil.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014, Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #include "luautil.h" 29 | 30 | inline static void 31 | adjust_index(int *index, int factor) 32 | { 33 | if (*index < 0) 34 | (*index) -= factor; 35 | } 36 | 37 | void 38 | luau_getarray(lua_State *L, int index, lua_Integer n) 39 | { 40 | lua_pushinteger(L, n); 41 | adjust_index(&index, 1); 42 | lua_gettable(L, index); 43 | } 44 | 45 | lua_Integer 46 | luau_getarray_integer(lua_State *L, int index, lua_Integer n) 47 | { 48 | luau_getarray(L, index, n); 49 | lua_Integer result = lua_tointeger(L, -1); 50 | lua_pop(L, 1); 51 | return result; 52 | } 53 | 54 | void 55 | luau_gettable(lua_State *L, int index, int field_index) 56 | { 57 | lua_pushvalue(L, field_index); 58 | adjust_index(&index, 1); 59 | lua_gettable(L, index); 60 | } 61 | 62 | void 63 | luau_settable(lua_State *L, int index, int field_index, int value_index) 64 | { 65 | lua_pushvalue(L, field_index); 66 | adjust_index(&value_index, 1); 67 | lua_pushvalue(L, value_index); 68 | adjust_index(&index, 2); 69 | lua_settable(L, index); 70 | } 71 | 72 | void 73 | luau_getmetatable(lua_State *L, int index, int field_index) 74 | { 75 | lua_getmetatable(L, index); 76 | adjust_index(&field_index, 1); 77 | luau_gettable(L, -1, field_index); 78 | /* pop metatable */ 79 | lua_remove(L, -2); 80 | } 81 | 82 | inline void 83 | luau_setmetatable(lua_State *L, const char *tname) 84 | { 85 | luaL_getmetatable(L, tname); 86 | lua_setmetatable(L, -2); 87 | } 88 | 89 | void * 90 | luau_malloc(lua_State *L, size_t size) 91 | { 92 | void * ud = NULL; 93 | lua_Alloc alloc = lua_getallocf(L, &ud); 94 | return alloc(ud, NULL, 0, size); 95 | } 96 | 97 | void 98 | luau_free(lua_State *L, void * ptr, size_t size) 99 | { 100 | void * ud = NULL; 101 | lua_Alloc alloc = lua_getallocf(L, &ud); 102 | alloc(ud, ptr, size, 0); 103 | } 104 | 105 | -------------------------------------------------------------------------------- /luautil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, 2014 Lourival Vieira Neto . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the Author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | #ifndef _LUA_UTIL_H_ 29 | #define _LUA_UTIL_H_ 30 | 31 | #ifndef _KERNEL 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | 38 | #define luau_isvalidref(ref) (ref != LUA_REFNIL && ref != LUA_NOREF) 39 | 40 | #define luau_ref(L) luaL_ref(L, LUA_REGISTRYINDEX) 41 | #define luau_unref(L, r) luaL_unref(L, LUA_REGISTRYINDEX, r) 42 | #define luau_getref(L, r) lua_rawgeti(L, LUA_REGISTRYINDEX, r) 43 | 44 | #define luau_tosize(L, index) ((size_t) lua_tointeger(L, index)) 45 | #define luau_pushsize(L, size) lua_pushinteger(L, (lua_Integer) size) 46 | 47 | void luau_getarray(lua_State *, int, lua_Integer); 48 | 49 | lua_Integer luau_getarray_integer(lua_State *, int, lua_Integer); 50 | 51 | void luau_gettable(lua_State *, int, int); 52 | 53 | void luau_settable(lua_State *, int, int, int); 54 | 55 | void luau_getmetatable(lua_State *, int, int); 56 | 57 | void luau_setmetatable(lua_State *, const char *); 58 | 59 | void * luau_malloc(lua_State *, size_t); 60 | 61 | void luau_free(lua_State *, void *, size_t); 62 | 63 | #endif /* _LUA_UTIL_H_ */ 64 | -------------------------------------------------------------------------------- /sys/endian.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Savio Sena , 3 | * Hisham Muhammad , Lourival Vieira Neto . 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. The name of the Author may not be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _ENDIAN_H_ 31 | #define _ENDIAN_H_ 32 | 33 | #ifndef _KERNEL 34 | #ifdef __MACH__ 35 | #include 36 | #else 37 | #include 38 | #endif 39 | #endif 40 | 41 | #ifdef __GNUC__ 42 | #define bswap64 __builtin_bswap64 43 | #ifndef BYTE_ORDER 44 | #define BYTE_ORDER __BYTE_ORDER__ 45 | #endif 46 | #ifndef LITTLE_ENDIAN 47 | #define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ 48 | #endif 49 | #ifndef BIG_ENDIAN 50 | #define BIG_ENDIAN __ORDER_BIG_ENDIAN__ 51 | #endif 52 | #endif 53 | 54 | #endif /* _ENDIAN_H_ */ 55 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "luadata.h" 10 | 11 | typedef unsigned char byte_t; 12 | 13 | int 14 | main(void) 15 | { 16 | /* create a new Lua state */ 17 | lua_State *L = luaL_newstate(); 18 | 19 | /* open luadata library */ 20 | #if LUA_VERSION_NUM >= 502 21 | luaL_requiref(L, "data", luaopen_data, 1); 22 | #else 23 | luaopen_data(L); 24 | #endif 25 | lua_pop(L, 1); /* remove lib */ 26 | 27 | /* load a script */ 28 | assert(luaL_dofile(L, "ctest.lua") == 0); 29 | 30 | /* get the filter function */ 31 | lua_getglobal(L, "filter"); 32 | 33 | /* create a new data ptr */ 34 | size_t data_size = 3; 35 | byte_t *data_ptr = (byte_t *) malloc(data_size); 36 | data_ptr[0] = 0xAB; 37 | data_ptr[1] = 0xCD; 38 | data_ptr[2] = 0xEF; 39 | 40 | /* create a new data object */ 41 | int rd = ldata_newref(L, data_ptr, data_size); 42 | 43 | /* call data_filter(d)*/ 44 | assert(lua_pcall(L, 1, 1, 0) == 0); 45 | 46 | /* get filter result */ 47 | int passed = lua_toboolean(L, -1); 48 | assert(passed); 49 | 50 | /* unregister the Lua data object */ 51 | ldata_unref(L, rd); 52 | 53 | /* now we can safely free the data pointer */ 54 | free(data_ptr); 55 | data_ptr = NULL; 56 | data_size = 0; 57 | 58 | /* get the access_global function */ 59 | lua_getglobal(L, "access_global"); 60 | 61 | /* call access_global() to try to access a data with a freed ptr */ 62 | assert(lua_pcall(L, 0, 1, 0) == 0); 63 | 64 | /* should return nil */ 65 | assert(lua_isnil(L, -1)); 66 | 67 | /* get a pointer of data object created by the Lua script */ 68 | lua_getglobal(L, "d"); 69 | data_ptr = (byte_t *) ldata_topointer(L, -1, &data_size); 70 | assert(data_ptr != NULL); 71 | 72 | /* check size and values */ 73 | assert(data_size == 4); 74 | assert(data_ptr[0] == 0xFF); 75 | assert(data_ptr[1] == 0xEE); 76 | assert(data_ptr[2] == 0xDD); 77 | assert(data_ptr[3] == 0x00); 78 | lua_pop(L, 1); 79 | 80 | /* remove data object refered by 'd' from Lua */ 81 | lua_pushnil(L); 82 | lua_setglobal(L, "d"); 83 | lua_gc(L, LUA_GCCOLLECT, 0); 84 | 85 | lua_getglobal(L, "d"); 86 | data_ptr = (byte_t *) ldata_topointer(L, -1, &data_size); 87 | assert(data_ptr == NULL); 88 | assert(data_size == 0); 89 | 90 | printf("test passed ;-)\n"); 91 | return 0; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | local data = require'data' 2 | 3 | -- create a new data object 4 | d1 = data.new{0x0f} 5 | 6 | -- with no layout applied, __index and __newindex should return nil 7 | d1.no = 0xdead 8 | assert(d1.no == nil) 9 | 10 | -- create and apply a data layout 11 | d1:layout{byte = {0, 8}, lsb = {7, 1}} 12 | 13 | -- access the whole byte 14 | assert(d1.byte == 0x0f) 15 | 16 | -- set 0 to the least significant bit 17 | d1.lsb = 0 18 | 19 | -- access the whole byte again 20 | assert(d1.byte == 0x0e) 21 | 22 | -- create a new layout 23 | l = data.layout{ 24 | uint16be = {0, 16}, 25 | uint16le = {0, 16, 'number', 'le'}, 26 | uint4 = {16, 4}, 27 | uint9 = {20, 9}, 28 | overflow = {32, 1}, 29 | } 30 | 31 | -- create a new data object 32 | d2 = data.new{0xaa, 0xbb, 0xcc, 0xdd} 33 | 34 | -- check byte length of d2 35 | assert(#d2 == 4) 36 | 37 | -- apply the layout 'l' to data 'd2' 38 | d2:layout(l) 39 | 40 | -- access 2 bytes using big-endian ordering 41 | assert(d2.uint16be == 0xaabb) 42 | 43 | -- access 2 bytes using little-endian ordering 44 | assert(d2.uint16le == 0xbbaa) 45 | 46 | -- access 4 bits 47 | assert(d2.uint4 == 0xc) 48 | 49 | -- access out of bounds 50 | assert(d2.overflow == nil) 51 | 52 | -- create a new data segment, where offset = 1, length = 3 53 | d3 = d2:segment(1, 3) 54 | 55 | -- check bit length of d3 56 | assert(#d3 == 3) 57 | 58 | -- apply the layout 'l' into data 'd3' 59 | d3:layout(l) 60 | 61 | -- access the first 16 bits of 'd3' segment 62 | assert(d3.uint16be == 0xbbcc) 63 | 64 | -- create a new data segment, where offset = 1, length is unbounded 65 | d4 = d3:segment(1) 66 | 67 | -- apply the layout 'l' into data 'd4' 68 | d4:layout(l) 69 | 70 | -- access the first 16 bits of 'd4' segment 71 | assert(d4.uint16be == 0xccdd) 72 | 73 | -- create a new data segment comprehending the whole original data 74 | d5 = d2:segment() 75 | 76 | -- apply the layout 'l' into data 'd5' 77 | d5:layout(l) 78 | 79 | -- set 0xf into 'uint4' position 80 | d5.uint4 = 0xf 81 | 82 | -- check that it was set 83 | assert(d5.uint4 == 0xf) 84 | 85 | -- check that d5 points to the same raw data of d2 86 | assert(d2.uint4 == 0xf) 87 | 88 | -- force the collecting of d2, d3, d4 89 | d2 = nil 90 | d3 = nil 91 | d4 = nil 92 | collectgarbage() 93 | 94 | -- check that d5 is still valid 95 | assert(d5.uint4 == 0xf) 96 | 97 | -- create a new data object with 2 bytes 98 | d = data.new(2) 99 | d:layout(l) 100 | d.uint16be = 0xBEEF 101 | assert(d.uint16be == 0xBEEF) 102 | 103 | d = data.new(128) 104 | l = data.layout{ 105 | toobig = {0, 65}, 106 | uint64 = {0, 64}, 107 | } 108 | 109 | d:layout(l) 110 | d.uint64 = -1 111 | assert(d.toobig == nil) 112 | assert(d.uint64 == -1) 113 | 114 | -- create a new data object from a string 115 | d = data.new'\a' 116 | d:layout{ascii = {1, 7}} 117 | assert(d.ascii == 7) 118 | 119 | -- create a string field in a layout 120 | d6 = data.new("abcdef") 121 | d6:layout{str = {0, 6, 's'}, overflow = {1, 6, 's'}} 122 | 123 | assert(d6.str == "abcdef") 124 | assert(d6.overflow == nil) 125 | 126 | d6.str = "hij" 127 | assert(d6.str == "hijdef") 128 | 129 | -- check invalid data creation 130 | d = data.new() 131 | assert(d == nil) 132 | 133 | d = data.new(0) 134 | assert(d == nil) 135 | 136 | d = data.new{} 137 | assert(d == nil) 138 | 139 | d = data.new('') 140 | assert(d == nil) 141 | 142 | print("test passed ;-)") 143 | --------------------------------------------------------------------------------