| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588 |
- /*
- @module zbuff
- @summary c内存数据操作库
- @version 0.1
- @date 2021.03.31
- @video https://www.bilibili.com/video/BV1gr4y1V7HN
- @tag LUAT_USE_ZBUFF
- @demo zbuff
- */
- #include "luat_base.h"
- #include "luat_zbuff.h"
- #define LUAT_LOG_TAG "zbuff"
- #include "luat_log.h"
- #ifndef LUAT_CONF_ZBUFF_DEFAULT_TYPE
- #ifdef LUAT_USE_PSRAM
- #define LUAT_CONF_ZBUFF_DEFAULT_TYPE LUAT_HEAP_PSRAM
- #else
- #define LUAT_CONF_ZBUFF_DEFAULT_TYPE LUAT_HEAP_SRAM
- #endif
- #endif
- //在buff对象后添加数据,返回增加的字节数
- static int add_bytes(luat_zbuff_t *buff, const char *source, size_t len)
- {
- if (buff->len - buff->cursor < len)
- len = buff->len - buff->cursor;
- memcpy(buff->addr + buff->cursor, source, len);
- buff->cursor += len;
- return len;
- }
- #define SET_POINT_1(buff, point, color) \
- if (color % 2) \
- buff->addr[point / 8] |= 1 << (7 - point % 8); \
- else \
- buff->addr[point / 8] &= ~(1 << (7 - point % 8))
- #define SET_POINT_4(buff, point, color) \
- buff->addr[point / 2] &= (point % 2) ? 0xf0 : 0x0f; \
- buff->addr[point / 2] |= (point % 2) ? color : (color * 0x10)
- #define SET_POINT_8(buff, point, color) buff->addr[point] = color
- #define SET_POINT_16(buff, point, color) \
- buff->addr[point * 2] = color / 0x100; \
- buff->addr[point * 2 + 1] = color % 0x100
- #define SET_POINT_24(buff, point, color) \
- buff->addr[point * 3] = color / 0x10000; \
- buff->addr[point * 3 + 1] = color % 0x10000 / 0x100; \
- buff->addr[point * 3 + 2] = color % 0x100
- #define SET_POINT_32(buff, point, color) \
- buff->addr[point] = color / 0x1000000; \
- buff->addr[point + 1] = color % 0x1000000 / 0x10000; \
- buff->addr[point + 2] = color % 0x10000 / 0x100; \
- buff->addr[point + 3] = color % 0x100
- #define SET_POINT_CASE(n, point, color) \
- case n: \
- SET_POINT_##n(buff, point, color); \
- break
- //更改某点的颜色
- #define set_framebuffer_point(buff, point, color) \
- switch (buff->bit) \
- { \
- SET_POINT_CASE(1, (point), (color)); \
- SET_POINT_CASE(4, (point), (color)); \
- SET_POINT_CASE(8, (point), (color)); \
- SET_POINT_CASE(16, (point), (color)); \
- SET_POINT_CASE(24, (point), (color)); \
- SET_POINT_CASE(32, (point), (color)); \
- default: \
- break; \
- }
- #define GET_POINT_1(buff, point) (buff->addr[point / 8] >> (7 - point % 8)) % 2
- #define GET_POINT_4(buff, point) (buff->addr[point / 2] >> ((point % 2) ? 0 : 4)) % 0x10
- #define GET_POINT_8(buff, point) buff->addr[point]
- #define GET_POINT_16(buff, point) buff->addr[point * 2] * 0x100 + buff->addr[point * 2 + 1]
- #define GET_POINT_24(buff, point) \
- buff->addr[point * 3] * 0x10000 + buff->addr[point * 3 + 1] * 0x100 + buff->addr[point * 3 + 2]
- #define GET_POINT_32(buff, point) \
- buff->addr[point] * 0x1000000 + buff->addr[point + 1] * 0x10000 + buff->addr[point + 2] * 0x100 + buff->addr[point + 3]
- #define GET_POINT_CASE(n, point) \
- case n: \
- return GET_POINT_##n(buff, point); \
- //获取某点的颜色
- static uint32_t get_framebuffer_point(luat_zbuff_t *buff,uint32_t point)
- {
- switch (buff->bit)
- {
- GET_POINT_CASE(1, point);
- GET_POINT_CASE(4, point);
- GET_POINT_CASE(8, point);
- GET_POINT_CASE(16, point);
- GET_POINT_CASE(24, point);
- GET_POINT_CASE(32, point);
- default:
- break;
- }
- return 0;
- }
- /**
- 创建zbuff
- @api zbuff.create(length,data,type)
- @int 字节数
- @any 可选参数,number时为填充数据,string时为填充字符串
- @number 可选参数,内存类型默认自动选择
- @return object zbuff对象,如果创建失败会返回nil
- @usage
- -- 创建zbuff
- local buff = zbuff.create(1024) -- 空白的
- local buff = zbuff.create(1024, 0x33) --创建一个初值全为0x33的内存区域
- local buff = zbuff.create(1024, "123321456654") -- 创建,并填充一个已有字符串的内容
- -- 创建framebuff用的zbuff
- -- zbuff.create({width,height,bit},data,type)
- -- table 宽度、高度、色位深度
- @int 可选参数,填充数据
- @number 可选参数,内存类型
- @return object zbuff对象,如果创建失败会返回nil
- @usage
- -- 创建zbuff
- local buff = zbuff.create({128,160,16})--创建一个128*160的framebuff
- local buff = zbuff.create({128,160,16},0xf800)--创建一个128*160的framebuff,初始状态红色
- */
- static int l_zbuff_create(lua_State *L)
- {
- size_t len;
- uint32_t width = 0,height = 0;
- uint8_t bit = 0;
- if (lua_istable(L, 1)){
- lua_rawgeti(L, 1, 3);
- lua_rawgeti(L, 1, 2);
- lua_rawgeti(L, 1, 1);
- width = luaL_checkinteger(L, -1);
- height = luaL_checkinteger(L, -2);
- bit = luaL_checkinteger(L, -3);
- if (bit != 1 && bit != 4 && bit != 8 && bit != 16 && bit != 24 && bit != 32) return 0;
- len = (width * height * bit - 1) / 8 + 1;
- lua_pop(L, 3);
- } else {
- len = luaL_checkinteger(L, 1);
- }
- if (len <= 0) return 0;
- if (len >= 64*1024) {
- LLOGI("create large size: %d kbyte, trigger force GC", len / 1024);
- lua_gc(L, LUA_GCCOLLECT, 0);
- lua_gc(L, LUA_GCCOLLECT, 0);
- }
- luat_zbuff_t *buff = (luat_zbuff_t *)lua_newuserdata(L, sizeof(luat_zbuff_t));
- if (buff == NULL) return 0;
- if (lua_isinteger(L, 3)){
- buff->type = luaL_optinteger(L, 3, LUAT_CONF_ZBUFF_DEFAULT_TYPE);
- } else {
- buff->type = LUAT_CONF_ZBUFF_DEFAULT_TYPE;
- }
- buff->addr = (uint8_t *)luat_heap_opt_malloc(buff->type,len);
- if (buff->addr == NULL){
- // 尝试垃圾回收后再分配一次
- LLOGI("create size: %d byte but memory not enough, trigger GC", len);
- lua_gc(L, LUA_GCCOLLECT, 0);
- lua_gc(L, LUA_GCCOLLECT, 0);
- buff->addr = (uint8_t *)luat_heap_opt_malloc(buff->type,len);
- }
- if (buff->addr == NULL){
- LLOGW("create size: %d byte but memory not enough!!!", len);
- lua_pushnil(L);
- lua_pushstring(L, "memory not enough");
- return 2;
- }
- buff->len = len;
- buff->cursor = 0;
- if (lua_istable(L, 1)){
- buff->width = width;
- buff->height = height;
- buff->bit = bit;
- if (lua_isinteger(L, 2)){
- LUA_INTEGER initial = luaL_checkinteger(L, 2);
- uint32_t i;
- for (i = 0; i < buff->width * buff->height; i++){
- set_framebuffer_point(buff, i, initial);
- }
- }
- }else{
- buff->width = buff->height = buff->bit = 0;
- if (lua_isinteger(L, 2)){
- memset(buff->addr, luaL_checkinteger(L, 2) % 0x100, len);
- }
- else if (lua_isstring(L, 2)){
- const char *data = luaL_optlstring(L, 2, "", &len);
- if (len > buff->len) len = buff->len; //防止越界
- memcpy(buff->addr, data, len);
- buff->cursor = len;
- }else{
- memset(buff->addr, 0, len);
- }
- }
- luaL_setmetatable(L, LUAT_ZBUFF_TYPE);
- return 1;
- }
- /**
- zbuff写数据(从当前指针位置开始;执行后指针会向后移动)
- @api buff:write(para,...)
- @any 写入buff的数据,string时为一个参数,number时可为多个参数
- @return number 数据成功写入的长度
- @usage
- -- 类file的读写操作
- local len = buff:write("123") -- 写入数据, 指针相应地往后移动,返回写入的数据长度
- local len = buff:write(0x1a,0x30,0x31,0x32,0x00,0x01) -- 按数值写入多个字节数据
- */
- static int l_zbuff_write(lua_State *L)
- {
- if (lua_isinteger(L, 2))
- {
- int len = 0;
- int data = 0;
- luat_zbuff_t *buff = tozbuff(L);
- while (lua_isinteger(L, 2 + len) && buff->cursor < buff->len)
- {
- data = luaL_checkinteger(L, 2 + len);
- *(uint8_t *)(buff->addr + buff->cursor) = data % 0x100;
- buff->cursor++;
- len++;
- }
- lua_pushinteger(L, len);
- return 1;
- }
- else
- {
- size_t len;
- const char *data = luaL_checklstring(L, 2, &len);
- luat_zbuff_t *buff = tozbuff(L);
- if (len + buff->cursor > buff->len) //防止越界
- {
- len = buff->len - buff->cursor;
- }
- memcpy(buff->addr + buff->cursor, data, len);
- buff->cursor = buff->cursor + len;
- lua_pushinteger(L, len);
- return 1;
- }
- }
- /**
- zbuff读数据(从当前指针位置开始;执行后指针会向后移动)
- @api buff:read(length)
- @int 读取buff中的字节数
- @return string 读取结果
- @usage
- -- 类file的读写操作
- local str = buff:read(3)
- */
- static int l_zbuff_read(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int read_num = luaL_optinteger(L, 2, 1);
- if (read_num > buff->len - buff->cursor) //防止越界
- {
- read_num = buff->len - buff->cursor;
- }
- if (read_num <= 0)
- {
- lua_pushlstring(L, NULL, 0);
- return 1;
- }
- char *return_str = (char *)luat_heap_opt_malloc(buff->type,read_num);
- if (return_str == NULL)
- {
- return 0;
- }
- memcpy(return_str, buff->addr + buff->cursor, read_num);
- lua_pushlstring(L, return_str, read_num);
- buff->cursor += read_num;
- luat_heap_opt_free(buff->type, return_str);
- return 1;
- }
- /**
- zbuff清空数据(与当前指针位置无关;执行后指针位置不变)
- @api buff:clear(num)
- @int 可选,默认为0。要设置为的值,不会改变buff指针位置
- @usage
- -- 全部初始化为0
- buff:clear(0)
- */
- static int l_zbuff_clear(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int num = luaL_optinteger(L, 2, 0);
- memset(buff->addr, num % 0x100, buff->len);
- return 0;
- }
- /**
- zbuff设置光标位置(可能与当前指针位置有关;执行后指针会被设置到指定位置)
- @api buff:seek(offset, base)
- @int 偏移长度
- @int where, 基点,默认zbuff.SEEK_SET。zbuff.SEEK_SET: 基点为 0 (文件开头),zbuff.SEEK_CUR: 基点为当前位置,zbuff.SEEK_END: 基点为文件尾
- @return int 设置光标后从buff开头计算起的光标的位置
- @usage
- buff:seek(0) -- 把光标设置到指定位置
- buff:seek(5,zbuff.SEEK_CUR)
- buff:seek(-3,zbuff.SEEK_END)
- */
- static int l_zbuff_seek(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int offset = luaL_checkinteger(L, 2);
- int whence = luaL_optinteger(L, 3, ZBUFF_SEEK_SET);
- switch (whence)
- {
- case ZBUFF_SEEK_SET:
- break;
- case ZBUFF_SEEK_CUR:
- offset = buff->cursor + offset;
- break;
- case ZBUFF_SEEK_END:
- offset = buff->len + offset;
- break;
- default:
- return 0;
- }
- if (offset <= 0)
- offset = 0;
- if (offset > buff->len)
- offset = buff->len;
- buff->cursor = offset;
- lua_pushinteger(L, buff->cursor);
- return 1;
- }
- //code from https://github.com/LuaDist/lpack/blob/master/lpack.c
- #define OP_STRING 'A'
- #define OP_FLOAT 'f'
- #define OP_DOUBLE 'd'
- #define OP_NUMBER 'n'
- #define OP_CHAR 'c'
- #define OP_BYTE 'b'
- #define OP_SHORT 'h'
- #define OP_USHORT 'H'
- #define OP_INT 'i'
- #define OP_UINT 'I'
- #define OP_LONG 'l'
- #define OP_ULONG 'L'
- #define OP_LITTLEENDIAN '<'
- #define OP_BIGENDIAN '>'
- #define OP_NATIVE '='
- #define isdigit(c) ((c) >= '0' && (c) <= '9')
- static void badcode(lua_State *L, int c)
- {
- char s[]="bad code `?'";
- s[sizeof(s)-3]=c;
- luaL_argerror(L,1,s);
- }
- static int doendian(int c)
- {
- int x=1;
- int e=*(char*)&x;
- if (c==OP_LITTLEENDIAN) return !e;
- if (c==OP_BIGENDIAN) return e;
- if (c==OP_NATIVE) return 0;
- return 0;
- }
- static void doswap(int swap, void *p, size_t n)
- {
- if (swap)
- {
- char *a = p;
- int i, j;
- for (i = 0, j = n - 1, n = n / 2; n--; i++, j--)
- {
- char t = a[i];
- a[i] = a[j];
- a[j] = t;
- }
- }
- }
- /**
- 将一系列数据按照格式字符转化,并写入(从当前指针位置开始;执行后指针会向后移动)
- @api buff:pack(format,val1, val2,...)
- @string 后面数据的格式(符号含义见下面的例子)
- @val 传入的数据,可以为多个数据
- @return int 成功写入的数据长度
- @usage
- buff:pack(">IIHA", 0x1234, 0x4567, 0x12,"abcdefg") -- 按格式写入几个数据
- -- A string
- -- f float
- -- d double
- -- n Lua number
- -- c char
- -- b byte / unsignen char
- -- h short
- -- H unsigned short
- -- i int
- -- I unsigned int
- -- l long
- -- L unsigned long
- -- < 小端
- -- > 大端
- -- = 默认大小端
- -- 例子
- buff:pack(
- ">IIHA", -- 格式字符串:大端序,依次为[4字节无符号整型, 4字节无符号整型, 2字节无符号短整型, 字符串]
- 0x1234, -- 参数1:整数值,写入为4字节(大端:00 00 12 34)
- 0x4567, -- 参数2:整数值,写入为4字节(大端:00 00 45 67)
- 0x12, -- 参数3:整数值,写入为2字节(大端:00 12)
- "abcdefg" -- 参数4:字符串,写入7字节ASCII码(61 62 63 64 65 66 67)
- )
- */
- #define PACKNUMBER(OP, T) \
- case OP: \
- { \
- T a = (T)luaL_checknumber(L, i++); \
- doswap(swap, &a, sizeof(a)); \
- write_len += add_bytes(buff, (void *)&a, sizeof(a)); \
- break; \
- }
- #define PACKINT(OP, T) \
- case OP: \
- { \
- T a = (T)luaL_checkinteger(L, i++); \
- doswap(swap, &a, sizeof(a)); \
- write_len += add_bytes(buff, (void *)&a, sizeof(a)); \
- break; \
- }
- static int l_zbuff_pack(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int i = 3;
- char *f = (char *)luaL_checkstring(L, 2);
- int swap = 0;
- int write_len = 0; //已写入长度
- while (*f)
- {
- if (buff->cursor == buff->len) //到头了
- break;
- int c = *f++;
- int N = 1;
- if (isdigit(*f))
- {
- N = 0;
- while (isdigit(*f))
- N = 10 * N + (*f++) - '0';
- }
- while (N--)
- {
- if (buff->cursor == buff->len) //到头了
- break;
- switch (c)
- {
- case OP_LITTLEENDIAN:
- case OP_BIGENDIAN:
- case OP_NATIVE:
- {
- swap = doendian(c);
- N = 0;
- break;
- }
- case OP_STRING:
- {
- size_t l;
- const char *a = luaL_checklstring(L, i++, &l);
- write_len += add_bytes(buff, a, l);
- break;
- }
- PACKNUMBER(OP_NUMBER, lua_Number)
- PACKNUMBER(OP_DOUBLE, double)
- PACKNUMBER(OP_FLOAT, float)
- PACKINT(OP_CHAR, char)
- PACKINT(OP_BYTE, unsigned char)
- PACKINT(OP_SHORT, short)
- PACKINT(OP_USHORT, unsigned short)
- PACKINT(OP_INT, int)
- PACKINT(OP_UINT, unsigned int)
- PACKINT(OP_LONG, long)
- PACKINT(OP_ULONG, unsigned long)
- case ' ':
- case ',':
- break;
- default:
- badcode(L, c);
- break;
- }
- }
- }
- lua_pushinteger(L, write_len);
- return 1;
- }
- #define UNPACKINT(OP, T) \
- case OP: \
- { \
- T a; \
- int m = sizeof(a); \
- if (i + m > len) \
- goto done; \
- memcpy(&a, s + i, m); \
- i += m; \
- doswap(swap, &a, m); \
- lua_pushinteger(L, (lua_Integer)a); \
- ++n; \
- break; \
- }
- #define UNPACKINT8(OP,T) \
- case OP: \
- { \
- T a; \
- int m=sizeof(a); \
- if (i+m>len) goto done; \
- memcpy(&a,s+i,m); \
- i+=m; \
- doswap(swap,&a,m); \
- int t = (a & 0x80)?(0xffffff00+a):a;\
- lua_pushinteger(L,(lua_Integer)t); \
- ++n; \
- break; \
- }
- #define UNPACKNUMBER(OP, T) \
- case OP: \
- { \
- T a; \
- int m = sizeof(a); \
- if (i + m > len) \
- goto done; \
- memcpy(&a, s + i, m); \
- i += m; \
- doswap(swap, &a, m); \
- lua_pushnumber(L, (lua_Number)a); \
- ++n; \
- break; \
- }
- /**
- 将一系列数据按照格式字符读取出来(从当前指针位置开始;执行后指针会向后移动)
- @api buff:unpack(format)
- @string 数据的格式(符号含义见上面pack接口的例子)
- @return int 成功读取的数据字节长度
- @return any 按格式读出来的数据
- @usage
- local cnt,a,b,c,s = buff:unpack(">IIHA10") -- 按格式读取几个数据
- --如果全部成功读取,cnt就是4+4+2+10=20
- */
- static int l_zbuff_unpack(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- char *f = (char *)luaL_checkstring(L, 2);
- size_t len = buff->len - buff->cursor;
- const char *s = (const char*)(buff->addr + buff->cursor);
- int i = 0;
- int n = 0;
- int swap = 0;
- lua_pushnil(L); //给个数占位用的
- while (*f)
- {
- int c = *f++;
- int N = 1;
- if (isdigit(*f))
- {
- N = 0;
- while (isdigit(*f))
- N = 10 * N + (*f++) - '0';
- if (N == 0 && c == OP_STRING)
- {
- lua_pushliteral(L, "");
- ++n;
- }
- }
- while (N--){
- if (!lua_checkstack(L, n))
- return luaL_error(L, "too many results to unpack");
- switch (c)
- {
- case OP_LITTLEENDIAN:
- case OP_BIGENDIAN:
- case OP_NATIVE:
- {
- swap = doendian(c);
- N = 0;
- break;
- }
- case OP_STRING:
- {
- ++N;
- if (i + N > len)
- goto done;
- lua_pushlstring(L, s + i, N);
- i += N;
- ++n;
- N = 0;
- break;
- }
- UNPACKNUMBER(OP_NUMBER, lua_Number)
- UNPACKNUMBER(OP_DOUBLE, double)
- UNPACKNUMBER(OP_FLOAT, float)
- UNPACKINT8(OP_CHAR, char)
- UNPACKINT(OP_BYTE, unsigned char)
- UNPACKINT(OP_SHORT, short)
- UNPACKINT(OP_USHORT, unsigned short)
- UNPACKINT(OP_INT, int)
- UNPACKINT(OP_UINT, unsigned int)
- UNPACKINT(OP_LONG, long)
- UNPACKINT(OP_ULONG, unsigned long)
- case ' ':
- case ',':
- break;
- default:
- badcode(L, c);
- break;
- }
- }
- }
- done:
- buff->cursor += i;
- lua_pushinteger(L, i);
- lua_replace(L, -n - 2);
- return n + 1;
- }
- /**
- 读取一个指定类型的数据(从当前指针位置开始;执行后指针会向后移动)
- @api buff:read类型()
- @注释 读取类型可为:I8、U8、I16、U16、I32、U32、I64、U64、F32、F64
- @return number 读取的数据,如果越界则为nil
- @usage
- local data = buff:readI8()
- local data = buff:readU32()
- */
- #define zread(n, t, f) \
- static int l_zbuff_read_##n(lua_State *L) \
- { \
- luat_zbuff_t *buff = tozbuff(L); \
- if (buff->len - buff->cursor < sizeof(t)) \
- return 0; \
- t tmp; \
- memcpy(&tmp, buff->addr + buff->cursor, sizeof(t)); \
- lua_push##f(L, tmp); \
- buff->cursor += sizeof(t); \
- return 1; \
- }
- zread(i8, int8_t, integer);
- zread(u8, uint8_t, integer);
- zread(i16, int16_t, integer);
- zread(u16, uint16_t, integer);
- zread(i32, int32_t, integer);
- zread(u32, uint32_t, integer);
- zread(i64, int64_t, integer);
- zread(u64, uint64_t, integer);
- zread(f32, float, number);
- zread(f64, double, number);
- /**
- 写入一个指定类型的数据(从当前指针位置开始;执行后指针会向后移动)
- @api buff:write类型()
- @number 待写入的数据
- @注释 写入类型可为:I8、U8、I16、U16、I32、U32、I64、U64、F32、F64
- @return number 成功写入的长度
- @usage
- local len = buff:writeI8(10)
- local len = buff:writeU32(1024)
- */
- #define zwrite(n, t, f) \
- static int l_zbuff_write_##n(lua_State *L) \
- { \
- luat_zbuff_t *buff = tozbuff(L); \
- if (buff->len - buff->cursor < sizeof(t)) \
- { \
- lua_pushinteger(L, 0); \
- return 1; \
- } \
- t tmp = (t)luaL_check##f(L, 2); \
- memcpy(buff->addr + buff->cursor, &(tmp), sizeof(t)); \
- buff->cursor += sizeof(t); \
- lua_pushinteger(L, sizeof(t)); \
- return 1; \
- }
- zwrite(i8, int8_t, integer);
- zwrite(u8, uint8_t, integer);
- zwrite(i16, int16_t, integer);
- zwrite(u16, uint16_t, integer);
- zwrite(i32, int32_t, integer);
- zwrite(u32, uint32_t, integer);
- zwrite(i64, int64_t, integer);
- zwrite(u64, uint64_t, integer);
- zwrite(f32, float, number);
- zwrite(f64, double, number);
- /**
- 按起始位置和长度取出数据(与当前指针位置无关;执行后指针位置不变)
- @api buff:toStr(offset,length)
- @int 数据的起始位置(起始位置为0),默认值也是0
- @int 数据的长度,默认是全部数据
- @return string 读出来的数据
- @usage
- local s = buff:toStr(0,5)--读取开头的五个字节数据
- local s = buff:toStr() -- 取出整个zbuff的数据
- local s = buff:toStr(0, buff:used()) -- 取出已使用的部分, 与buff:query()一样
- */
- static int l_zbuff_toStr(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int start = luaL_optinteger(L, 2, 0);
- if (start > buff->len)
- start = buff->len;
- int len = luaL_optinteger(L, 3, buff->len);
- if (start + len > buff->len)
- len = buff->len - start;
- lua_pushlstring(L, (const char*)(buff->addr + start), len);
- return 1;
- }
- /**
- 获取zbuff对象的长度(与当前指针位置无关;执行后指针位置不变)
- @api buff:len()
- @return int zbuff对象的长度
- @usage
- len = buff:len()
- len = #buff
- */
- static int l_zbuff_len(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- lua_pushinteger(L, buff->len);
- return 1;
- }
- /**
- 设置buff对象的FrameBuffer属性(与当前指针位置无关;执行后指针位置不变)
- @api buff:setFrameBuffer(width,height,bit,color)
- @int FrameBuffer的宽度
- @int FrameBuffer的高度
- @int FrameBuffer的色位深度
- @int FrameBuffer的初始颜色
- @return bool 设置成功会返回true
- @usage
- result = buff:setFrameBuffer(320,240,16,0xffff)
- */
- static int l_zbuff_set_frame_buffer(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- //检查空间够不够
- if((luaL_checkinteger(L, 2) * luaL_checkinteger(L, 3) * luaL_checkinteger(L, 4) - 1) / 8 + 1 > buff->len)
- return 0;
- buff->width = luaL_checkinteger(L,2);
- buff->height = luaL_checkinteger(L,3);
- buff->bit = luaL_checkinteger(L,4);
- if (lua_isinteger(L, 5))
- {
- LUA_INTEGER color = luaL_checkinteger(L, 5);
- uint32_t i;
- for (i = 0; i < buff->width * buff->height; i++)
- set_framebuffer_point(buff, i, color);
- }
- lua_pushboolean(L,1);
- return 1;
- }
- /**
- 设置或获取FrameBuffer某个像素点的颜色(与当前指针位置无关;执行后指针位置不变)
- @api buff:pixel(x,y,color)
- @int 与最左边的距离,范围是0~宽度-1
- @int 与最上边的距离,范围是0~高度-1
- @int 颜色,如果留空则表示获取该位置的颜色
- @return any 设置颜色时,设置成功会返回true;读取颜色时,返回颜色的值,读取失败返回nil
- @usage
- rerult = buff:pixel(0,3,0)
- color = buff:pixel(0,3)
- */
- static int l_zbuff_pixel(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- uint32_t x = luaL_checkinteger(L,2);
- uint32_t y = luaL_checkinteger(L,3);
- if(x>=buff->width||y>=buff->height)
- return 0;
- if (lua_isinteger(L, 4))
- {
- LUA_INTEGER color = luaL_checkinteger(L, 4);
- set_framebuffer_point(buff, x + y * buff->width, color);
- lua_pushboolean(L,1);
- return 1;
- }
- else
- {
- lua_pushinteger(L,get_framebuffer_point(buff,x + y * buff->width));
- return 1;
- }
- }
- /**
- 画一条线(与当前指针位置无关;执行后指针位置不变)
- @api buff:drawLine(x1,y1,x2,y2,color)
- @int 起始坐标点与最左边的距离,范围是0~宽度-1
- @int 起始坐标点与最上边的距离,范围是0~高度-1
- @int 结束坐标点与最左边的距离,范围是0~宽度-1
- @int 结束坐标点与最上边的距离,范围是0~高度-1
- @int 可选,颜色,默认为0
- @return bool 画成功会返回true
- @usage
- rerult = buff:drawLine(0,0,2,3,0xffff)
- */
- #define abs(n) (n>0?n:-n)
- static int l_zbuff_draw_line(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if(buff->width<=0) return 0;//不是framebuffer数据
- uint32_t x0 = luaL_checkinteger(L,2);
- uint32_t y0 = luaL_checkinteger(L,3);
- uint32_t x1 = luaL_checkinteger(L,4);
- uint32_t y1 = luaL_checkinteger(L,5);
- uint32_t color = luaL_optinteger(L,6,0);
- //代码参考https://blog.csdn.net/qq_43405938/article/details/102700922
- int x = x0, y = y0, dx = x1 - x0, dy = y1 - y0;
- int max = (abs(dy) > abs(dx)) ? abs(dy) : abs(dx);
- int min = (abs(dy) > abs(dx)) ? abs(dx) : abs(dy);
- float e = 2 * min - max;
- for (int i = 0; i < max; i++)
- {
- if(x>=0&&y>=0&&x<buff->width&&y<buff->height)
- set_framebuffer_point(buff,x+y*buff->width,color);
- if (e >= 0)
- {
- e = e - 2 * max;
- (abs(dy) > abs(dx)) ? (dx >= 0 ? x++ : x--) : (dy >= 0 ? y++ : y--);
- }
- e += 2 * min;
- (abs(dy) > abs(dx)) ? (dy >= 0 ? y++ : y--) : (dx >= 0 ? x++ : x--);
- }
- lua_pushboolean(L,1);
- return 1;
- }
- /**
- 画一个矩形(与当前指针位置无关;执行后指针位置不变)
- @api buff:drawRect(x1,y1,x2,y2,color,fill)
- @int 起始坐标点与最左边的距离,范围是0~宽度-1
- @int 起始坐标点与最上边的距离,范围是0~高度-1
- @int 结束坐标点与最左边的距离,范围是0~宽度-1
- @int 结束坐标点与最上边的距离,范围是0~高度-1
- @int 可选,颜色,默认为0
- @bool 可选,是否在内部填充,默认nil
- @return bool 画成功会返回true
- @usage
- rerult = buff:drawRect(0,0,2,3,0xffff)
- */
- #define CHECK0(n,max) if(n<0)n=0;if(n>=max)n=max-1
- static int l_zbuff_draw_rectangle(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if(buff->width<=0) return 0;//不是framebuffer数据
- int32_t x1 = (int32_t)luaL_checkinteger(L,2); CHECK0(x1,buff->width);
- int32_t y1 = (int32_t)luaL_checkinteger(L,3); CHECK0(y1,buff->height);
- int32_t x2 = (int32_t)luaL_checkinteger(L,4); CHECK0(x2,buff->width);
- int32_t y2 = (int32_t)luaL_checkinteger(L,5); CHECK0(y2,buff->height);
- int32_t color = (int32_t)luaL_optinteger(L,6,0);
- uint8_t fill = lua_toboolean(L,7);
- int x,y;
- int32_t xmax=x1>x2?x1:x2,xmin=x1>x2?x2:x1,ymax=y1>y2?y1:y2,ymin=y1>y2?y2:y1;
- if(fill){
- for(x=xmin;x<=xmax;x++)
- for(y=ymin;y<=ymax;y++)
- set_framebuffer_point(buff,x+y*buff->width,color);
- }else{
- for(x=xmin;x<=xmax;x++){
- set_framebuffer_point(buff,x+ymin*buff->width,color);
- set_framebuffer_point(buff,x+ymax*buff->width,color);
- }
- for(y=ymin;y<=ymax;y++){
- set_framebuffer_point(buff,xmin+y*buff->width,color);
- set_framebuffer_point(buff,xmax+y*buff->width,color);
- }
- }
- lua_pushboolean(L,1);
- return 1;
- }
- /**
- 画一个圆形(与当前指针位置无关;执行后指针位置不变)
- @api buff:drawCircle(x,y,r,color,fill)
- @int **圆心**与最左边的距离,范围是0~宽度-1
- @int **圆心**与最上边的距离,范围是0~高度-1
- @int 圆的半径
- @int 可选,圆的颜色,默认为0
- @bool 可选,是否在内部填充,默认nil
- @return bool 画成功会返回true
- @usage
- rerult = buff:drawCircle(15,5,3,0xC)
- rerult = buff:drawCircle(15,5,3,0xC,true)
- */
- #define DRAW_CIRCLE_ALL(buff, xc, yc, x, y, c) \
- { \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc + x) + (yc + y) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc - x) + (yc + y) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc + x) + (yc - y) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc - x) + (yc - y) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc + y) + (yc + x) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc - y) + (yc + x) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc + y) + (yc - x) * buff->width, c); \
- if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
- set_framebuffer_point(buff, (xc - y) + (yc - x) * buff->width, c); \
- }
- static int l_zbuff_draw_circle(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if(buff->width<=0) return 0;//不是framebuffer数据
- int32_t xc = luaL_checkinteger(L,2);
- int32_t yc = luaL_checkinteger(L,3);
- int32_t r = luaL_checkinteger(L,4);
- int32_t color = luaL_optinteger(L,5,0);
- uint8_t fill = lua_toboolean(L,6);
- //代码参考https://www.cnblogs.com/wlzy/p/8695226.html
- //圆不在可见区域
- if (xc + r < 0 || xc - r >= buff->width || yc + r < 0 || yc - r >= buff->height)
- return 0;
- int x = 0, y = r, yi, d;
- d = 3 - 2 * r;
- while (x <= y)
- {
- if (fill)
- {
- for (yi = x; yi <= y; yi++)
- DRAW_CIRCLE_ALL(buff, xc, yc, x, yi, color);
- }
- else
- {
- DRAW_CIRCLE_ALL(buff, xc, yc, x, y, color);
- }
- if (d < 0)
- {
- d = d + 4 * x + 6;
- }
- else
- {
- d = d + 4 * (x - y) + 10;
- y--;
- }
- x++;
- }
- lua_pushboolean(L,1);
- return 1;
- }
- /**
- 以下标形式进行数据读写(与当前指针位置无关;执行后指针位置不变)
- @api buff[n]
- @int 第几个数据,以0开始的下标(C标准)
- @return number 该位置的数据
- @usage
- buff[0] = 0xc8
- local data = buff[0]
- */
- static int l_zbuff_index(lua_State *L)
- {
- //luat_zbuff_t **pp = luaL_checkudata(L, 1, LUAT_ZBUFF_TYPE);
- // int i;
- luaL_getmetatable(L, LUAT_ZBUFF_TYPE);
- lua_pushvalue(L, 2);
- lua_rawget(L, -2);
- if (lua_isnil(L, -1))
- {
- /* found no method, so get value from userdata. */
- luat_zbuff_t *buff = tozbuff(L);
- int o = luaL_checkinteger(L, 2);
- if (o >= buff->len)
- return 0;
- lua_pushinteger(L, buff->addr[o]);
- return 1;
- };
- return 1;
- }
- static int l_zbuff_newindex(lua_State *L)
- {
- if (lua_isinteger(L, 2))
- {
- luat_zbuff_t *buff = tozbuff(L);
- if (lua_isinteger(L, 2))
- {
- int o = luaL_checkinteger(L, 2);
- int n = luaL_checkinteger(L, 3) % 256;
- if (o > buff->len)
- return 0;
- buff->addr[o] = n;
- }
- }
- return 0;
- }
- // __gc l_zbuff_gc为zbuff默认gc函数,gc调用时会释放申请内存并gc掉zbuff,下面为用户手动调用注释
- /**
- 释放zbuff所申请内存 注意:gc时会自动释放zbuff以及zbuff所申请内存,所以通常无需调用此函数,调用前请确认您已清楚此函数用处!调用此函数并不会释放掉zbuff,仅会释放掉zbuff所申请的内存,zbuff需等gc时自动释放!!!
- @api buff:free()
- @usage
- buff:free()
- */
- static int l_zbuff_gc(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if (buff->addr){
- luat_heap_opt_free(buff->type,buff->addr);
- buff->addr = NULL;
- buff->len = 0;
- buff->used = 0;
- }
- return 0;
- }
- int __zbuff_resize(luat_zbuff_t *buff, uint32_t new_size)
- {
- void *p = luat_heap_opt_realloc(buff->type, buff->addr, new_size?new_size:1);
- if (p)
- {
- buff->addr = p;
- buff->len = new_size;
- buff->used = (buff->len > buff->used)?buff->used:buff->len;
- return 0;
- }
- else
- {
- LLOGE("zbuff realloc failed %d -> %d", buff->len, new_size);
- return -1;
- }
- }
- /**
- 调整zbuff实际分配空间的大小,类似于realloc的效果,new = realloc(old, n),可以扩大或者缩小(如果缩小后len小于了used,那么used=新len)
- @api buff:resize(n)
- @int 新空间大小
- @usage
- buff:resize(20)
- */
- static int l_zbuff_resize(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if (lua_isinteger(L, 2))
- {
- uint32_t n = luaL_checkinteger(L, 2);
- __zbuff_resize(buff, n);
- }
- return 0;
- }
- /**
- zbuff动态写数据,类似于memcpy效果,当原有空间不足时动态扩大空间
- @api buff:copy(start, para,...)
- @int 写入buff的起始位置,如果不为数字,则为buff的used,如果小于0,则从used往前数,-1 = used - 1
- @any 写入buff的数据,string或zbuff者时为一个参数,number时可为多个参数
- @return number 数据成功写入的长度
- @usage
- local len = buff:copy(nil, "123") -- 类似于memcpy(&buff[used], "123", 3) used+= 3 从buff开始写入数据,指针相应地往后移动
- local len = buff:copy(0, "123") -- 类似于memcpy(&buff[0], "123", 3) if (used < 3) used = 3 从位置0写入数据,指针有可能会移动
- local len = buff:copy(2, 0x1a,0x30,0x31,0x32,0x00,0x01) -- 类似于memcpy(&buff[2], [0x1a,0x30,0x31,0x32,0x00,0x01], 6) if (used < (2+6)) used = (2+6)从位置2开始,按数值写入多个字节数据
- local len = buff:copy(9, buff2) -- 类似于memcpy(&buff[9], &buff2[0], buff2的used) if (used < (9+buff2的used)) used = (9+buff2的used) 从位置9开始,合并入buff2里0~used的内容
- local len = buff:copy(5, buff2, 10, 1024) -- 类似于memcpy(&buff[5], &buff2[10], 1024) if (used < (5+1024)) used = (5+1024)
- */
- static int l_zbuff_copy(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int temp_cursor = luaL_optinteger(L, 2, buff->used);
- if (temp_cursor < 0)
- {
- temp_cursor = buff->used + temp_cursor;
- if (temp_cursor < 0)
- {
- lua_pushinteger(L, 0);
- return 1;
- }
- }
- if (lua_isinteger(L, 3))
- {
- int len = 0;
- int data = 0;
- while (lua_isinteger(L, 3 + len))
- {
- if (temp_cursor > buff->len)
- {
- if (__zbuff_resize(buff, temp_cursor * 2))
- {
- lua_pushinteger(L, len);
- return 1;
- }
- }
- data = luaL_checkinteger(L, 3 + len);
- *(uint8_t *)(buff->addr + temp_cursor) = data % 0x100;
- temp_cursor++;
- len++;
- }
- buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
- lua_pushinteger(L, len);
- return 1;
- }
- else if (lua_isstring(L, 3))
- {
- size_t len;
- const char *data = luaL_checklstring(L, 3, &len);
- if (len + temp_cursor > buff->len) //防止越界
- {
- if (__zbuff_resize(buff, buff->len + len + temp_cursor))
- {
- lua_pushinteger(L, 0);
- return 1;
- }
- }
- memcpy(buff->addr + temp_cursor, data, len);
- temp_cursor = temp_cursor + len;
- buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
- lua_pushinteger(L, len);
- return 1;
- }
- else if (lua_isuserdata(L, 3))
- {
- luat_zbuff_t *copy_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
- uint32_t start = luaL_optinteger(L, 4, 0);
- uint32_t len = luaL_optinteger(L, 5, copy_buff->used);
- if (len + temp_cursor > buff->len) //防止越界
- {
- if (__zbuff_resize(buff, buff->len + len + temp_cursor))
- {
- lua_pushinteger(L, 0);
- return 1;
- }
- }
- memcpy(buff->addr + temp_cursor, copy_buff->addr + start, len);
- temp_cursor += len;
- buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
- lua_pushinteger(L, len);
- return 1;
- }
- lua_pushinteger(L, 0);
- return 1;
- }
- /**
- 设置/获取zbuff里最后一个数据位置指针到首地址的偏移量,来表示zbuff内已有有效数据量大小,注意这个不同于分配的空间大小,由于seek()会改变最后一个数据位置指针,因此也会影响到used()返回值。
- @api buff:used()
- @int 最后一个数据位置指针到首地址的偏移量,不能是负数,如果不填则不更改当前值,如果该值超过了buff总量,则自动改为buff总量
- @return int 有效数据量大小
- @usage
- buff:used() --直接返回当前的有效数据量大小
- buff:used(123) --设置当前的有效数据量为123字节,如果buff本身不到123字节,比如120字节,则会改成120,返回值是120
- */
- static int l_zbuff_used(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- if (lua_isinteger(L, 2))
- {
- size_t temp_cursor = luaL_optinteger(L, 2, buff->used);
- if (temp_cursor > buff->len)
- {
- buff->used = buff->len;
- }
- else
- {
- buff->used = temp_cursor;
- }
- }
- lua_pushinteger(L, buff->used);
- return 1;
- }
- /**
- 删除zbuff 0~used范围内的一段数据,注意只是改变了used的值,并不是真的在ram里去清除掉数据
- @api buff:del(offset,length)
- @int 起始位置start, 默认0,如果<0则从used往前数,比如 -1 那么start= used - 1
- @int 长度del_len,默认为used,如果start + del_len数值大于used,会强制调整del_len = used - start
- @usage
- buff:del(1,4) --从位置1开始删除4个字节数据
- buff:del(-1,4) --从位置used-1开始删除4个字节数据,但是这肯定会超过used,所以del_len会调整为1,实际上就是删掉了最后一个字节
- */
- static int l_zbuff_del(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int start = luaL_optinteger(L, 2, 0);
- if (start < 0)
- {
- start += buff->used;
- if (start < 0)
- {
- return 0;
- }
- }
- if (start >= (int)buff->used)
- return 0;
- uint32_t len = luaL_optinteger(L, 3, buff->used);
- if (start + len > buff->used)
- len = buff->used - start;
- if (!len)
- {
- return 0;
- }
- if ((start + len) == buff->used)
- {
- buff->used = start;
- }
- else
- {
- uint32_t rest = buff->used - len;
- memmove(buff->addr + start, buff->addr + start + len, rest);
- buff->used = rest;
- }
- return 0;
- }
- static uint32_t BytesGetBe32(const void *ptr)
- {
- const uint8_t *p = (const uint8_t *)ptr;
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
- }
- static uint32_t BytesGetLe32(const void *ptr)
- {
- const uint8_t *p = (const uint8_t *)ptr;
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
- }
- /**
- 按起始位置和长度0~used范围内取出数据,如果是1,2,4,8字节,且填写了isbigend参数,则根据isbigend,issigned,isfloat转换成浮点或者整形
- @api buff:query(offset,length,isbigend,issigned,isfloat)
- @int 数据的起始位置(起始位置为0)
- @int 数据的长度
- @boolean 是否是大端格式,如果为nil,则不会转换,直接字节流输出,false为小端格式,true为大端格式
- @boolean 是否是有符号的,默认为false
- @boolean 是否是浮点型,默认为false
- @return string 读出来的数据,如果取出数据是1,2,4,8字节,且isbigend填写了true或者false,则输出浮点或者整形
- @usage
- local s = buff:query(0,5)--读取开头的五个字节数据
- */
- static int l_zbuff_query(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int start = luaL_optinteger(L, 2, 0);
- if (start < 0)
- {
- start += buff->used;
- if (start < 0)
- {
- lua_pushnil(L);
- return 1;
- }
- }
- if (start > buff->used)
- start = buff->used;
- uint32_t len = luaL_optinteger(L, 3, buff->used);
- if (start + len > buff->used)
- len = buff->used - start;
- if (!len)
- {
- lua_pushnil(L);
- return 1;
- }
- if (lua_isboolean(L, 4) && (len <= 8))
- {
- int is_bigend = lua_toboolean(L, 4);
- int is_float = 0;
- int is_signed = 0;
- if (lua_isboolean(L, 5))
- {
- is_signed = lua_toboolean(L, 5);
- }
- if (lua_isboolean(L, 6))
- {
- is_float = lua_toboolean(L, 6);
- }
- uint8_t *p = buff->addr + start;
- uint8_t uc;
- int16_t s;
- uint16_t us;
- int32_t i;
- // uint32_t ui;
- int64_t l;
- float f;
- double d;
- switch(len)
- {
- case 1:
- if (is_signed)
- {
- i = (p[0] & 0x80)?(p[0] + 0xffffff00):p[0];
- lua_pushinteger(L, i);
- }
- else
- {
- uc = p[0];
- lua_pushinteger(L, uc);
- }
- break;
- case 2:
- if (is_bigend)
- {
- us = (p[0] << 8) | p[1];
- }
- else
- {
- us = (p[1] << 8) | p[0];
- }
- if (is_signed)
- {
- s = us;
- lua_pushinteger(L, s);
- }
- else
- {
- lua_pushinteger(L, us);
- }
- break;
- case 4:
- if (is_float)
- {
- memcpy(&f, p, len);
- lua_pushnumber(L, f);
- }
- else
- {
- if (is_bigend)
- {
- i = BytesGetBe32(p);
- }
- else
- {
- i = BytesGetLe32(p);
- }
- lua_pushinteger(L, i);
- }
- break;
- case 8:
- if (is_float)
- {
- memcpy(&d, p, len);
- lua_pushnumber(L, d);
- }
- else
- {
- if (is_bigend)
- {
- l = BytesGetBe32(p + 4) | ((int64_t)BytesGetBe32(p) << 32);
- }
- else
- {
- l = BytesGetLe32(p) | ((int64_t)BytesGetLe32(p + 4) << 32);
- }
- lua_pushinteger(L, l);
- }
- break;
- default:
- lua_pushlstring(L, (const char*)(buff->addr + start), len);
- break;
- }
- return 1;
- }
- lua_pushlstring(L, (const char*)(buff->addr + start), len);
- return 1;
- }
- /**
- zbuff的类似于memset操作,类似于memset(&buff[start], num, len),当然有ram越界保护,会对len有一定的限制
- @api buff:set(start, num, len)
- @int 可选,开始位置,默认为0,
- @int 可选,默认为0。要设置为的值
- @int 可选,长度,默认为全部空间,如果超出范围了,会自动截断
- @usage
- -- 全部初始化为0
- buff:set() --等同于 memset(buff, 0, sizeof(buff))
- buff:set(8) --等同于 memset(&buff[8], 0, sizeof(buff) - 8)
- buff:set(0, 0x55) --等同于 memset(buff, 0x55, sizeof(buff))
- buff:set(4, 0xaa, 12) --等用于 memset(&buff[4], 0xaa, 12)
- */
- static int l_zbuff_set(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- int num = luaL_optinteger(L, 3, 0);
- uint32_t start = luaL_optinteger(L, 2, 0);
- uint32_t len = luaL_optinteger(L, 4, buff->len);
- memset(buff->addr + start, num & 0x00ff, ((len + start) > buff->len)?(buff->len - start):len);
- return 0;
- }
- /**
- zbuff的类似于memcmp操作,类似于memcmp(&buff[start], &buff2[start2], len)
- @api buff:isEqual(start, buff2, start2, len)
- @int 可选,开始位置,默认为0,
- @zbuff 比较的对象
- @int 可选,比较的对象的开始位置,默认为0
- @int 比较长度
- @return boolean true相等,false不相等
- @return int 相等返回0,不相等返回第一个不相等位置的序号
- @usage
- local result, offset = buff:isEqual(1, buff2, 2, 10) --等同于memcmp(&buff[1], &buff2[2], 10)
- */
- static int l_zbuff_equal(lua_State *L)
- {
- luat_zbuff_t *buff = tozbuff(L);
- uint32_t offset1 = luaL_optinteger(L, 2, 0);
- luat_zbuff_t *buff2 = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
- uint32_t offset2 = luaL_optinteger(L, 4, 0);
- uint32_t len = luaL_optinteger(L, 5, 1);
- uint32_t i;
- uint8_t *b1 = buff->addr + offset1;
- uint8_t *b2 = buff2->addr + offset2;
- for(i = 0; i < len; i++) {
- if (b1[i] != b2[i]) {
- lua_pushboolean(L, 0);
- lua_pushinteger(L, i);
- return 2;
- }
- }
- lua_pushboolean(L, 1);
- lua_pushinteger(L, 0);
- return 2;
- }
- /**
- 将当前zbuff数据转base64,输出到下一个zbuff中
- @api buff:toBase64(dst)
- @userdata zbuff指针
- @return int 转换后的实际长度
- @usage
- -- dst:len必须大于buff:used() * 1.35 + 3, 确保有足够空间存放base64数据
- buff:toBase64(dst)
- */
- #include "luat_str.h"
- static int l_zbuff_to_base64(lua_State *L) {
- luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 1, LUAT_ZBUFF_TYPE));
- luat_zbuff_t *buff2 = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
- size_t olen = 0;
- int ret = luat_str_base64_encode(buff2->addr, buff2->len, &olen, buff->addr, buff->used);
- if (ret) {
- LLOGE("zbuff toBase64 failed %d", ret);
- lua_pushinteger(L, 0);
- }
- else {
- buff2->used = olen;
- lua_pushinteger(L, olen);
- }
- return 1;
- };
- static const luaL_Reg lib_zbuff[] = {
- {"write", l_zbuff_write},
- {"read", l_zbuff_read},
- {"clear", l_zbuff_clear},
- {"seek", l_zbuff_seek},
- {"pack", l_zbuff_pack},
- {"unpack", l_zbuff_unpack},
- {"get", l_zbuff_index},
- {"readI8", l_zbuff_read_i8},
- {"readI16", l_zbuff_read_i16},
- {"readI32", l_zbuff_read_i32},
- {"readI64", l_zbuff_read_i64},
- {"readU8", l_zbuff_read_u8},
- {"readU16", l_zbuff_read_u16},
- {"readU32", l_zbuff_read_u32},
- {"readU64", l_zbuff_read_u64},
- {"readF32", l_zbuff_read_f32},
- {"readF64", l_zbuff_read_f64},
- {"writeI8", l_zbuff_write_i8},
- {"writeI16", l_zbuff_write_i16},
- {"writeI32", l_zbuff_write_i32},
- {"writeI64", l_zbuff_write_i64},
- {"writeU8", l_zbuff_write_u8},
- {"writeU16", l_zbuff_write_u16},
- {"writeU32", l_zbuff_write_u32},
- {"writeU64", l_zbuff_write_u64},
- {"writeF32", l_zbuff_write_f32},
- {"writeF64", l_zbuff_write_f64},
- {"toStr", l_zbuff_toStr},
- {"len", l_zbuff_len},
- {"setFrameBuffer", l_zbuff_set_frame_buffer},
- {"pixel", l_zbuff_pixel},
- {"drawLine", l_zbuff_draw_line},
- {"drawRect", l_zbuff_draw_rectangle},
- {"drawCircle", l_zbuff_draw_circle},
- //{"__index", l_zbuff_index},
- //{"__len", l_zbuff_len},
- //{"__newindex", l_zbuff_newindex},
- {"free", l_zbuff_gc},
- //以下为扩展用法,数据的增减操作尽量不要和上面的read,write一起使用,对数值指针的用法不一致
- {"copy", l_zbuff_copy},
- {"set", l_zbuff_set},
- {"query",l_zbuff_query},
- {"del", l_zbuff_del},
- {"resize", l_zbuff_resize},
- {"reSize", l_zbuff_resize},
- {"used", l_zbuff_used},
- {"isEqual", l_zbuff_equal},
- {"toBase64", l_zbuff_to_base64},
- {NULL, NULL}};
- static int luat_zbuff_meta_index(lua_State *L) {
- if (lua_isinteger(L, 2)) {
- return l_zbuff_index(L);
- }
- if (lua_isstring(L, 2)) {
- const char* keyname = luaL_checkstring(L, 2);
- //printf("zbuff keyname = %s\n", keyname);
- int i = 0;
- while (1) {
- if (lib_zbuff[i].name == NULL) break;
- if (!strcmp(keyname, lib_zbuff[i].name)) {
- lua_pushcfunction(L, lib_zbuff[i].func);
- return 1;
- }
- i++;
- }
- }
- return 0;
- }
- static void createmeta(lua_State *L)
- {
- luaL_newmetatable(L, LUAT_ZBUFF_TYPE); /* create metatable for file handles */
- // lua_pushvalue(L, -1); /* push metatable */
- // lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
- // luaL_setfuncs(L, lib_zbuff, 0); /* add file methods to new metatable */
- //luaL_setfuncs(L, lib_zbuff_metamethods, 0);
- //luaL_setfuncs(L, lib_zbuff, 0);
- lua_pushcfunction(L, l_zbuff_len);
- lua_setfield(L, -2, "__len");
- lua_pushcfunction(L, l_zbuff_gc);
- lua_setfield(L, -2, "__gc");
- lua_pushcfunction(L, luat_zbuff_meta_index);
- lua_setfield(L, -2, "__index");
- lua_pushcfunction(L, l_zbuff_newindex);
- lua_setfield(L, -2, "__newindex");
- lua_pop(L, 1); /* pop new metatable */
- //luaL_newlib(L, lib_zbuff);
- }
- #include "rotable2.h"
- static const rotable_Reg_t reg_zbuff[] =
- {
- {"create", ROREG_FUNC(l_zbuff_create)},
- //@const SEEK_SET number 以头为基点
- {"SEEK_SET", ROREG_INT(ZBUFF_SEEK_SET)},
- //@const SEEK_CUR number 以当前位置为基点
- {"SEEK_CUR", ROREG_INT(ZBUFF_SEEK_CUR)},
- //@const SEEK_END number 以末尾为基点
- {"SEEK_END", ROREG_INT(ZBUFF_SEEK_END)},
- //@const HEAP_AUTO number 自动申请(如存在psram则在psram进行申请,如不存在或失败则在sram进行申请)
- {"HEAP_AUTO", ROREG_INT(LUAT_HEAP_AUTO)},
- //@const HEAP_SRAM number 在sram申请
- {"HEAP_SRAM", ROREG_INT(LUAT_HEAP_SRAM)},
- //@const HEAP_PSRAM number 在psram申请
- {"HEAP_PSRAM", ROREG_INT(LUAT_HEAP_PSRAM)},
- {NULL, ROREG_INT(0)
- }
- };
- LUAMOD_API int luaopen_zbuff(lua_State *L)
- {
- luat_newlib2(L, reg_zbuff);
- createmeta(L);
- return 1;
- }
|