改写 alien struct使其适配lua5.3

/*

** Library for packing/unpacking structures.

**

** Valid formats:

** x - pading

** b/B - signed/unsigned byte

** h/H - signed/unsigned short

** l/L - signed/unsigned long

** i/In - signed/unsigned integer with size `n‘ (default is size of int)

** cn - sequence of `n‘ chars (from/to a string); when packing, n==0 means

the whole string; when unpacking, n==0 means use the previous

read number as the string length

** s - zero-terminated string

** f - float

** d - doulbe

*/

#include <ctype.h>

#include <string.h>

#include "lua.h"

#include "lauxlib.h"

/* dummy structure to get alignment requirements */

struct cD {

char c;

double d;

};

static int getmaxalign (void) {

int ma = sizeof(int);

int e = sizeof(struct cD) - sizeof(double);

if (ma < e) ma = e;

return ma;

}

static int getendianess (const char **s, int *native_out) {

int endian;  /* 0 = little; 1 = big */

int native = 1;

if (*(char *)&native == 1)

native = 0;

if (**s == ‘>‘) {

endian = 1;

(*s)++;

}

else if (**s == ‘<‘) {

endian = 0;

(*s)++;

}

else

endian = native;

*native_out = native;

return endian;

}

static int getnum (const char **fmt, int df) {

if (!isdigit(**fmt))

return df;  /* no number */

else {

int a = 0;

do {

a = a*10 + *((*fmt)++) - ‘0‘;

} while (isdigit(**fmt));

return a;

}

}

static int optsize (char opt, const char **fmt) {

switch (opt) {

case ‘B‘: case ‘b‘: return 1;

case ‘H‘: case ‘h‘: return 2;

case ‘L‘: case ‘l‘: return 4;

case ‘f‘:  return sizeof(float);

case ‘d‘:  return sizeof(double);

case ‘x‘: return 1;

case ‘i‘: return getnum(fmt, sizeof(int));

case ‘c‘: return getnum(fmt, 1);

case ‘s‘: return 0;

default: return 1;  /* invalid code */

}

}

static int getalign (const char **fmt) {

if (**fmt != ‘!‘) return 1;  /* no alignment */

else {

(*fmt)++;

return getnum(fmt, getmaxalign());

}

}

static int gettoalign (lua_State *L, int align, int opt, int size) {

int toalign = (opt == ‘c‘ || opt == ‘s‘) ? 1 : size;

if (toalign > align) toalign = align;

if (toalign == 0 || (toalign & (toalign - 1)) != 0)

luaL_error(L, "alignment must be power of 2");

return toalign;

}

static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,

int size) {

unsigned char buff[sizeof(long)];

lua_Number n = luaL_checknumber(L, arg);

unsigned long value;

unsigned char *s;

int inc, i;

if (n < 0) {

value = (unsigned long)(-n);

value = (~value) + 1;  /* 2‘s complement */

}

else

value = (unsigned long)n;

if (endian == 0) {

inc = 1;

s = buff;

}

else {

inc = -1;

s = buff+(size-1);

}

for (i=0; i<size; i++) {

*s = (unsigned char)(value & 0xff);

s += inc;

value >>= 8;

}

luaL_addlstring(b, (char *)buff, size);

}

static void invertbytes (char *b, int size) {

int i = 0;

while (i < --size) {

char temp = b[i];

b[i++] = b[size];

b[size] = temp;

}

}

static void invalidformat (lua_State *L, char c) {

const char *msg = lua_pushfstring(L, "invalid format option [%c]", c);

luaL_argerror(L, 1, msg);

}

static int b_size (lua_State *L) {

int native;

const char *fmt = luaL_checkstring(L, 1);

int align;

int totalsize = 0;

getendianess(&fmt, &native);

align = getalign(&fmt);

while (*fmt) {

int opt = *fmt++;

int size = optsize(opt, &fmt);

int toalign = gettoalign(L, align, opt, size);

if (size == 0)

luaL_error(L, "options `c0‘ - `s‘ have undefined sizes");

totalsize += toalign - 1;

totalsize -= totalsize&(toalign-1);

totalsize += size;

}

lua_pushnumber(L, totalsize);

return 1;

}

static int b_pack (lua_State *L) {

luaL_Buffer b;

int native;

const char *fmt = luaL_checkstring(L, 1);

int endian = getendianess(&fmt, &native);

int align = getalign(&fmt);

int arg = 2;

int totalsize = 0;

lua_pushnil(L);  /* mark to separate arguments from string buffer */

luaL_buffinit(L, &b);

for (; *fmt; arg++) {

int opt = *fmt++;

int size = optsize(opt, &fmt);

int toalign = gettoalign(L, align, opt, size);

while ((totalsize&(toalign-1)) != 0) {

//luaL_putchar(&b, ‘\0‘);

luaL_addchar(&b, ‘\0‘);

totalsize++;

}

switch (opt) {

case ‘ ‘: break;  /* ignore white spaces */

case ‘b‘: case ‘B‘: case ‘h‘: case ‘H‘:

case ‘l‘: case ‘L‘: case ‘i‘: case ‘I‘: {  /* integer types */

putinteger(L, &b, arg, endian, size);

break;

}

case ‘x‘: {

arg--;  /* undo increment */

//luaL_putchar(&b, ‘\0‘);

luaL_addchar(&b, ‘\0‘);

break;

}

case ‘f‘: {

float f = (float)luaL_checknumber(L, arg);

if (endian != native) invertbytes((char *)&f, size);

luaL_addlstring(&b, (char *)&f, size);

break;

}

case ‘d‘: {

double d = luaL_checknumber(L, arg);

if (endian != native) invertbytes((char *)&d, size);

luaL_addlstring(&b, (char *)&d, size);

break;

}

case ‘c‘: case ‘s‘: {

size_t l;

const char *s = luaL_checklstring(L, arg, &l);

if (size == 0) size = l;

luaL_argcheck(L, l >= (size_t)size, arg, "string too short");

luaL_addlstring(&b, s, size);

if (opt == ‘s‘) {

//luaL_putchar(&b, ‘\0‘);  /* add zero at the end */

luaL_addchar(&b, ‘\0‘);

size++;

}

break;

}

default: invalidformat(L, opt);

}

totalsize += size;

}

luaL_pushresult(&b);

return 1;

}

static void getinteger (lua_State *L, const char *buff, int endian,

int withsign, int size) {

unsigned long l = 0;

int i, inc;

if (endian == 1)

inc = 1;

else {

inc = -1;

buff += size-1;

}

for (i=0; i<size; i++) {

l = (l<<8) + (unsigned char)(*buff);

buff += inc;

}

if (withsign) {  /* signed format? */

unsigned long mask = ~(0UL) << (size*8 - 1);

if (l & mask) {  /* negative value? */

l = (l^~(mask<<1)) + 1;

lua_pushnumber(L, -(lua_Number)l);

return;

}

}

lua_pushnumber(L, l);

}

static int b_unpack (lua_State *L) {

int native;

const char *fmt = luaL_checkstring(L, 1);

size_t ld;

int pos, align, endian;

const char *data;

if(lua_isuserdata(L, 2)) {

data = (const char*)lua_touserdata(L, 2);

ld = (size_t)luaL_checkinteger(L, 3);

pos = 0;

} else {

data = luaL_checklstring(L, 2, &ld);

//pos = luaL_optint(L, 3, 1) - 1;

pos = luaL_optinteger(L, 3, 1) - 1;

}

endian = getendianess(&fmt, &native);

align = getalign(&fmt);

lua_settop(L, 2);

while (*fmt) {

int opt = *fmt++;

int size = optsize(opt, &fmt);

int toalign = gettoalign(L, align, opt, size);

pos += toalign - 1;

pos -= pos&(toalign-1);

luaL_argcheck(L, pos+size <= (int)ld, 2, "data string too short");

switch (opt) {

case ‘ ‘: break;  /* ignore white spaces */

case ‘b‘: case ‘B‘: case ‘h‘: case ‘H‘:

case ‘l‘: case ‘L‘: case ‘i‘:  case ‘I‘: {  /* integer types */

int withsign = islower(opt);

getinteger(L, data+pos, endian, withsign, size);

break;

}

case ‘x‘: {

break;

}

case ‘f‘: {

float f;

memcpy(&f, data+pos, size);

if (endian != native) invertbytes((char *)&f, sizeof(f));

lua_pushnumber(L, f);

break;

}

case ‘d‘: {

double d;

memcpy(&d, data+pos, size);

if (endian != native) invertbytes((char *)&d, sizeof(d));

lua_pushnumber(L, d);

break;

}

case ‘c‘: {

if (size == 0) {

if (!lua_isnumber(L, -1))

luaL_error(L, "format `c0‘ needs a previous size");

size = lua_tonumber(L, -1);

lua_pop(L, 1);

luaL_argcheck(L, pos+size <= (int)ld, 2, "data string too short");

}

lua_pushlstring(L, data+pos, size);

break;

}

case ‘s‘: {

const char *e = (const char *)memchr(data+pos, ‘\0‘, ld - pos);

if (e == NULL)

luaL_error(L, "unfinished string in data");

size = (e - (data+pos)) + 1;

lua_pushlstring(L, data+pos, size - 1);

break;

}

default: invalidformat(L, opt);

}

pos += size;

}

lua_pushnumber(L, pos + 1);

return lua_gettop(L) - 2;

}

static const struct luaL_Reg thislib[] = {

{"pack", b_pack},

{"unpack", b_unpack},

{"size", b_size},

{NULL, NULL}

};

LUALIB_API int luaopen_alien_struct (lua_State *L) {

lua_getglobal(L, "alien");

if(lua_isnil(L, -1)) {

lua_newtable(L);

lua_pushvalue(L, -1);

lua_setglobal(L, "alien");

}

lua_newtable(L);

lua_pushvalue(L, -1);

lua_setfield(L, -3, "struct");

luaL_newlib(L, thislib);

return 1;

}

时间: 2024-08-28 16:28:09

改写 alien struct使其适配lua5.3的相关文章

改写 alien core使其可以适配lua5.3

/* Lua FFI using libffi */ /* Author: Fabio Mascarenhas */ /* License: MIT/X11 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "lua.h" #include "lualib.h" #include "

exists改写SQL,使其走正确的执行计划

数据库环境:SQL SERVER 2005 今天看到一条SQL,写得不是很复杂,返回7000多条数据,却执行了15s.SQL文本及各表的数据量如下: SELECT acinv_07.id_item , SUM(acinv_07.dec_endqty) dec_endqty FROM acinv_07 WHERE acinv_07.fiscal_year * 100 + acinv_07.fiscal_period = ( SELECT DISTINCT ctlm1101.fiscal_year

2.11 方法(Methods)

方法(Methods) 本页包含内容: 实例方法(Instance Methods) 类型方法(Type Methods) 方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-

Swift Programming Language ——实例方法(Instance Methods)和类型方法(Type Methods)

方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-C 中,类是唯一能定义方法的类型.但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活的在你创建的类型

Swift语法学习之 方法

方法:1.实例方法(OC中实例方法,通过创建实例调用) 2.类型方法(OC中的类方法,类名调用) 类.结构体.枚举都可以定义实例方法和类型方法:实例方法为给定类型的实例封装了具体的任务与功能.类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-C 中,类是唯一能定义方法的类型.但在 Swift 中,你不仅能选择是否要定义一个类/

Swift学习第五枪

方法(methods)和下表脚本(Subscripts) 实例方法(Instance Methods) 类型方法(Type Methods) 下表脚本(Subscripts) 方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objecti ve-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objec

Swift中文手册 -- Methods

方法 方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-C 中,类是唯一能定义方法的类型.但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活的在你创建

C++11标准教程

C++11,先前被称作C++0x,即ISO/IEC 14882:2011,是目前的C++编程语言的正式标准.它取代第二版标准ISO/IEC 14882:2003(第一版ISO/IEC 14882:1998公开于1998年,第二版于2003年更新,分别通称C++98以及C++03,两者差异很小).新的标准包含核心语言的新机能,而且扩展C++标准程序库,并入了大部分的C++ Technical Report 1程序库(数学的特殊函数除外).最新的消息被公开在 ISO C++ 委员会网站(英文). I

IOS开发语言Swift入门连载---方法

IOS开发语言Swift入门连载-方法 方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-C 中,类是唯一能定义方法的类型.但在 Swift 中,你不仅能选择是否要定义一个类