luat_lib_zbuff.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574
  1. /*
  2. @module zbuff
  3. @summary c内存数据操作库
  4. @version 0.1
  5. @date 2021.03.31
  6. @video https://www.bilibili.com/video/BV1gr4y1V7HN
  7. @tag LUAT_USE_ZBUFF
  8. @demo zbuff
  9. */
  10. #include "luat_base.h"
  11. #include "luat_zbuff.h"
  12. #define LUAT_LOG_TAG "zbuff"
  13. #include "luat_log.h"
  14. #ifndef LUAT_CONF_ZBUFF_DEFAULT_TYPE
  15. #ifdef LUAT_USE_PSRAM
  16. #define LUAT_CONF_ZBUFF_DEFAULT_TYPE LUAT_HEAP_PSRAM
  17. #else
  18. #define LUAT_CONF_ZBUFF_DEFAULT_TYPE LUAT_HEAP_SRAM
  19. #endif
  20. #endif
  21. //在buff对象后添加数据,返回增加的字节数
  22. static int add_bytes(luat_zbuff_t *buff, const char *source, size_t len)
  23. {
  24. if (buff->len - buff->cursor < len)
  25. len = buff->len - buff->cursor;
  26. memcpy(buff->addr + buff->cursor, source, len);
  27. buff->cursor += len;
  28. return len;
  29. }
  30. #define SET_POINT_1(buff, point, color) \
  31. if (color % 2) \
  32. buff->addr[point / 8] |= 1 << (7 - point % 8); \
  33. else \
  34. buff->addr[point / 8] &= ~(1 << (7 - point % 8))
  35. #define SET_POINT_4(buff, point, color) \
  36. buff->addr[point / 2] &= (point % 2) ? 0xf0 : 0x0f; \
  37. buff->addr[point / 2] |= (point % 2) ? color : (color * 0x10)
  38. #define SET_POINT_8(buff, point, color) buff->addr[point] = color
  39. #define SET_POINT_16(buff, point, color) \
  40. buff->addr[point * 2] = color / 0x100; \
  41. buff->addr[point * 2 + 1] = color % 0x100
  42. #define SET_POINT_24(buff, point, color) \
  43. buff->addr[point * 3] = color / 0x10000; \
  44. buff->addr[point * 3 + 1] = color % 0x10000 / 0x100; \
  45. buff->addr[point * 3 + 2] = color % 0x100
  46. #define SET_POINT_32(buff, point, color) \
  47. buff->addr[point] = color / 0x1000000; \
  48. buff->addr[point + 1] = color % 0x1000000 / 0x10000; \
  49. buff->addr[point + 2] = color % 0x10000 / 0x100; \
  50. buff->addr[point + 3] = color % 0x100
  51. #define SET_POINT_CASE(n, point, color) \
  52. case n: \
  53. SET_POINT_##n(buff, point, color); \
  54. break
  55. //更改某点的颜色
  56. #define set_framebuffer_point(buff, point, color) \
  57. switch (buff->bit) \
  58. { \
  59. SET_POINT_CASE(1, (point), (color)); \
  60. SET_POINT_CASE(4, (point), (color)); \
  61. SET_POINT_CASE(8, (point), (color)); \
  62. SET_POINT_CASE(16, (point), (color)); \
  63. SET_POINT_CASE(24, (point), (color)); \
  64. SET_POINT_CASE(32, (point), (color)); \
  65. default: \
  66. break; \
  67. }
  68. #define GET_POINT_1(buff, point) (buff->addr[point / 8] >> (7 - point % 8)) % 2
  69. #define GET_POINT_4(buff, point) (buff->addr[point / 2] >> ((point % 2) ? 0 : 4)) % 0x10
  70. #define GET_POINT_8(buff, point) buff->addr[point]
  71. #define GET_POINT_16(buff, point) buff->addr[point * 2] * 0x100 + buff->addr[point * 2 + 1]
  72. #define GET_POINT_24(buff, point) \
  73. buff->addr[point * 3] * 0x10000 + buff->addr[point * 3 + 1] * 0x100 + buff->addr[point * 3 + 2]
  74. #define GET_POINT_32(buff, point) \
  75. buff->addr[point] * 0x1000000 + buff->addr[point + 1] * 0x10000 + buff->addr[point + 2] * 0x100 + buff->addr[point + 3]
  76. #define GET_POINT_CASE(n, point) \
  77. case n: \
  78. return GET_POINT_##n(buff, point); \
  79. //获取某点的颜色
  80. static uint32_t get_framebuffer_point(luat_zbuff_t *buff,uint32_t point)
  81. {
  82. switch (buff->bit)
  83. {
  84. GET_POINT_CASE(1, point);
  85. GET_POINT_CASE(4, point);
  86. GET_POINT_CASE(8, point);
  87. GET_POINT_CASE(16, point);
  88. GET_POINT_CASE(24, point);
  89. GET_POINT_CASE(32, point);
  90. default:
  91. break;
  92. }
  93. return 0;
  94. }
  95. /**
  96. 创建zbuff
  97. @api zbuff.create(length,data,type)
  98. @int 字节数
  99. @any 可选参数,number时为填充数据,string时为填充字符串
  100. @number 可选参数,内存类型默认自动选择
  101. @return object zbuff对象,如果创建失败会返回nil
  102. @usage
  103. -- 创建zbuff
  104. local buff = zbuff.create(1024) -- 空白的
  105. local buff = zbuff.create(1024, 0x33) --创建一个初值全为0x33的内存区域
  106. local buff = zbuff.create(1024, "123321456654") -- 创建,并填充一个已有字符串的内容
  107. -- 创建framebuff用的zbuff
  108. -- zbuff.create({width,height,bit},data,type)
  109. -- table 宽度、高度、色位深度
  110. @int 可选参数,填充数据
  111. @number 可选参数,内存类型
  112. @return object zbuff对象,如果创建失败会返回nil
  113. @usage
  114. -- 创建zbuff
  115. local buff = zbuff.create({128,160,16})--创建一个128*160的framebuff
  116. local buff = zbuff.create({128,160,16},0xf800)--创建一个128*160的framebuff,初始状态红色
  117. */
  118. static int l_zbuff_create(lua_State *L)
  119. {
  120. size_t len;
  121. uint32_t width = 0,height = 0;
  122. uint8_t bit = 0;
  123. if (lua_istable(L, 1)){
  124. lua_rawgeti(L, 1, 3);
  125. lua_rawgeti(L, 1, 2);
  126. lua_rawgeti(L, 1, 1);
  127. width = luaL_checkinteger(L, -1);
  128. height = luaL_checkinteger(L, -2);
  129. bit = luaL_checkinteger(L, -3);
  130. if (bit != 1 && bit != 4 && bit != 8 && bit != 16 && bit != 24 && bit != 32) return 0;
  131. len = (width * height * bit - 1) / 8 + 1;
  132. lua_pop(L, 3);
  133. } else {
  134. len = luaL_checkinteger(L, 1);
  135. }
  136. if (len <= 0) return 0;
  137. luat_zbuff_t *buff = (luat_zbuff_t *)lua_newuserdata(L, sizeof(luat_zbuff_t));
  138. if (buff == NULL) return 0;
  139. if (lua_isinteger(L, 3)){
  140. buff->type = luaL_optinteger(L, 3, LUAT_CONF_ZBUFF_DEFAULT_TYPE);
  141. } else {
  142. buff->type = LUAT_CONF_ZBUFF_DEFAULT_TYPE;
  143. }
  144. buff->addr = (uint8_t *)luat_heap_opt_malloc(buff->type,len);
  145. if (buff->addr == NULL){
  146. lua_pushnil(L);
  147. lua_pushstring(L, "memory not enough");
  148. return 2;
  149. }
  150. buff->len = len;
  151. buff->cursor = 0;
  152. if (lua_istable(L, 1)){
  153. buff->width = width;
  154. buff->height = height;
  155. buff->bit = bit;
  156. if (lua_isinteger(L, 2)){
  157. LUA_INTEGER initial = luaL_checkinteger(L, 2);
  158. uint32_t i;
  159. for (i = 0; i < buff->width * buff->height; i++){
  160. set_framebuffer_point(buff, i, initial);
  161. }
  162. }
  163. }else{
  164. buff->width = buff->height = buff->bit = 0;
  165. if (lua_isinteger(L, 2)){
  166. memset(buff->addr, luaL_checkinteger(L, 2) % 0x100, len);
  167. }
  168. else if (lua_isstring(L, 2)){
  169. const char *data = luaL_optlstring(L, 2, "", &len);
  170. if (len > buff->len) len = buff->len; //防止越界
  171. memcpy(buff->addr, data, len);
  172. buff->cursor = len;
  173. }else{
  174. memset(buff->addr, 0, len);
  175. }
  176. }
  177. luaL_setmetatable(L, LUAT_ZBUFF_TYPE);
  178. return 1;
  179. }
  180. /**
  181. zbuff写数据(从当前指针位置开始;执行后指针会向后移动)
  182. @api buff:write(para,...)
  183. @any 写入buff的数据,string时为一个参数,number时可为多个参数
  184. @return number 数据成功写入的长度
  185. @usage
  186. -- 类file的读写操作
  187. local len = buff:write("123") -- 写入数据, 指针相应地往后移动,返回写入的数据长度
  188. local len = buff:write(0x1a,0x30,0x31,0x32,0x00,0x01) -- 按数值写入多个字节数据
  189. */
  190. static int l_zbuff_write(lua_State *L)
  191. {
  192. if (lua_isinteger(L, 2))
  193. {
  194. int len = 0;
  195. int data = 0;
  196. luat_zbuff_t *buff = tozbuff(L);
  197. while (lua_isinteger(L, 2 + len) && buff->cursor < buff->len)
  198. {
  199. data = luaL_checkinteger(L, 2 + len);
  200. *(uint8_t *)(buff->addr + buff->cursor) = data % 0x100;
  201. buff->cursor++;
  202. len++;
  203. }
  204. lua_pushinteger(L, len);
  205. return 1;
  206. }
  207. else
  208. {
  209. size_t len;
  210. const char *data = luaL_checklstring(L, 2, &len);
  211. luat_zbuff_t *buff = tozbuff(L);
  212. if (len + buff->cursor > buff->len) //防止越界
  213. {
  214. len = buff->len - buff->cursor;
  215. }
  216. memcpy(buff->addr + buff->cursor, data, len);
  217. buff->cursor = buff->cursor + len;
  218. lua_pushinteger(L, len);
  219. return 1;
  220. }
  221. }
  222. /**
  223. zbuff读数据(从当前指针位置开始;执行后指针会向后移动)
  224. @api buff:read(length)
  225. @int 读取buff中的字节数
  226. @return string 读取结果
  227. @usage
  228. -- 类file的读写操作
  229. local str = buff:read(3)
  230. */
  231. static int l_zbuff_read(lua_State *L)
  232. {
  233. luat_zbuff_t *buff = tozbuff(L);
  234. int read_num = luaL_optinteger(L, 2, 1);
  235. if (read_num > buff->len - buff->cursor) //防止越界
  236. {
  237. read_num = buff->len - buff->cursor;
  238. }
  239. if (read_num <= 0)
  240. {
  241. lua_pushlstring(L, NULL, 0);
  242. return 1;
  243. }
  244. char *return_str = (char *)luat_heap_opt_malloc(buff->type,read_num);
  245. if (return_str == NULL)
  246. {
  247. return 0;
  248. }
  249. memcpy(return_str, buff->addr + buff->cursor, read_num);
  250. lua_pushlstring(L, return_str, read_num);
  251. buff->cursor += read_num;
  252. luat_heap_opt_free(buff->type, return_str);
  253. return 1;
  254. }
  255. /**
  256. zbuff清空数据(与当前指针位置无关;执行后指针位置不变)
  257. @api buff:clear(num)
  258. @int 可选,默认为0。要设置为的值,不会改变buff指针位置
  259. @usage
  260. -- 全部初始化为0
  261. buff:clear(0)
  262. */
  263. static int l_zbuff_clear(lua_State *L)
  264. {
  265. luat_zbuff_t *buff = tozbuff(L);
  266. int num = luaL_optinteger(L, 2, 0);
  267. memset(buff->addr, num % 0x100, buff->len);
  268. return 0;
  269. }
  270. /**
  271. zbuff设置光标位置(可能与当前指针位置有关;执行后指针会被设置到指定位置)
  272. @api buff:seek(offset, base)
  273. @int 偏移长度
  274. @int where, 基点,默认zbuff.SEEK_SET。zbuff.SEEK_SET: 基点为 0 (文件开头),zbuff.SEEK_CUR: 基点为当前位置,zbuff.SEEK_END: 基点为文件尾
  275. @return int 设置光标后从buff开头计算起的光标的位置
  276. @usage
  277. buff:seek(0) -- 把光标设置到指定位置
  278. buff:seek(5,zbuff.SEEK_CUR)
  279. buff:seek(-3,zbuff.SEEK_END)
  280. */
  281. static int l_zbuff_seek(lua_State *L)
  282. {
  283. luat_zbuff_t *buff = tozbuff(L);
  284. int offset = luaL_checkinteger(L, 2);
  285. int whence = luaL_optinteger(L, 3, ZBUFF_SEEK_SET);
  286. switch (whence)
  287. {
  288. case ZBUFF_SEEK_SET:
  289. break;
  290. case ZBUFF_SEEK_CUR:
  291. offset = buff->cursor + offset;
  292. break;
  293. case ZBUFF_SEEK_END:
  294. offset = buff->len + offset;
  295. break;
  296. default:
  297. return 0;
  298. }
  299. if (offset <= 0)
  300. offset = 0;
  301. if (offset > buff->len)
  302. offset = buff->len;
  303. buff->cursor = offset;
  304. lua_pushinteger(L, buff->cursor);
  305. return 1;
  306. }
  307. //code from https://github.com/LuaDist/lpack/blob/master/lpack.c
  308. #define OP_STRING 'A'
  309. #define OP_FLOAT 'f'
  310. #define OP_DOUBLE 'd'
  311. #define OP_NUMBER 'n'
  312. #define OP_CHAR 'c'
  313. #define OP_BYTE 'b'
  314. #define OP_SHORT 'h'
  315. #define OP_USHORT 'H'
  316. #define OP_INT 'i'
  317. #define OP_UINT 'I'
  318. #define OP_LONG 'l'
  319. #define OP_ULONG 'L'
  320. #define OP_LITTLEENDIAN '<'
  321. #define OP_BIGENDIAN '>'
  322. #define OP_NATIVE '='
  323. #define isdigit(c) ((c) >= '0' && (c) <= '9')
  324. static void badcode(lua_State *L, int c)
  325. {
  326. char s[]="bad code `?'";
  327. s[sizeof(s)-3]=c;
  328. luaL_argerror(L,1,s);
  329. }
  330. static int doendian(int c)
  331. {
  332. int x=1;
  333. int e=*(char*)&x;
  334. if (c==OP_LITTLEENDIAN) return !e;
  335. if (c==OP_BIGENDIAN) return e;
  336. if (c==OP_NATIVE) return 0;
  337. return 0;
  338. }
  339. static void doswap(int swap, void *p, size_t n)
  340. {
  341. if (swap)
  342. {
  343. char *a = p;
  344. int i, j;
  345. for (i = 0, j = n - 1, n = n / 2; n--; i++, j--)
  346. {
  347. char t = a[i];
  348. a[i] = a[j];
  349. a[j] = t;
  350. }
  351. }
  352. }
  353. /**
  354. 将一系列数据按照格式字符转化,并写入(从当前指针位置开始;执行后指针会向后移动)
  355. @api buff:pack(format,val1, val2,...)
  356. @string 后面数据的格式(符号含义见下面的例子)
  357. @val 传入的数据,可以为多个数据
  358. @return int 成功写入的数据长度
  359. @usage
  360. buff:pack(">IIHA", 0x1234, 0x4567, 0x12,"abcdefg") -- 按格式写入几个数据
  361. -- A string
  362. -- f float
  363. -- d double
  364. -- n Lua number
  365. -- c char
  366. -- b byte / unsignen char
  367. -- h short
  368. -- H unsigned short
  369. -- i int
  370. -- I unsigned int
  371. -- l long
  372. -- L unsigned long
  373. -- < 小端
  374. -- > 大端
  375. -- = 默认大小端
  376. -- 例子
  377. buff:pack(
  378. ">IIHA", -- 格式字符串:大端序,依次为[4字节无符号整型, 4字节无符号整型, 2字节无符号短整型, 字符串]
  379. 0x1234, -- 参数1:整数值,写入为4字节(大端:00 00 12 34)
  380. 0x4567, -- 参数2:整数值,写入为4字节(大端:00 00 45 67)
  381. 0x12, -- 参数3:整数值,写入为2字节(大端:00 12)
  382. "abcdefg" -- 参数4:字符串,写入7字节ASCII码(61 62 63 64 65 66 67)
  383. )
  384. */
  385. #define PACKNUMBER(OP, T) \
  386. case OP: \
  387. { \
  388. T a = (T)luaL_checknumber(L, i++); \
  389. doswap(swap, &a, sizeof(a)); \
  390. write_len += add_bytes(buff, (void *)&a, sizeof(a)); \
  391. break; \
  392. }
  393. #define PACKINT(OP, T) \
  394. case OP: \
  395. { \
  396. T a = (T)luaL_checkinteger(L, i++); \
  397. doswap(swap, &a, sizeof(a)); \
  398. write_len += add_bytes(buff, (void *)&a, sizeof(a)); \
  399. break; \
  400. }
  401. static int l_zbuff_pack(lua_State *L)
  402. {
  403. luat_zbuff_t *buff = tozbuff(L);
  404. int i = 3;
  405. char *f = (char *)luaL_checkstring(L, 2);
  406. int swap = 0;
  407. int write_len = 0; //已写入长度
  408. while (*f)
  409. {
  410. if (buff->cursor == buff->len) //到头了
  411. break;
  412. int c = *f++;
  413. int N = 1;
  414. if (isdigit(*f))
  415. {
  416. N = 0;
  417. while (isdigit(*f))
  418. N = 10 * N + (*f++) - '0';
  419. }
  420. while (N--)
  421. {
  422. if (buff->cursor == buff->len) //到头了
  423. break;
  424. switch (c)
  425. {
  426. case OP_LITTLEENDIAN:
  427. case OP_BIGENDIAN:
  428. case OP_NATIVE:
  429. {
  430. swap = doendian(c);
  431. N = 0;
  432. break;
  433. }
  434. case OP_STRING:
  435. {
  436. size_t l;
  437. const char *a = luaL_checklstring(L, i++, &l);
  438. write_len += add_bytes(buff, a, l);
  439. break;
  440. }
  441. PACKNUMBER(OP_NUMBER, lua_Number)
  442. PACKNUMBER(OP_DOUBLE, double)
  443. PACKNUMBER(OP_FLOAT, float)
  444. PACKINT(OP_CHAR, char)
  445. PACKINT(OP_BYTE, unsigned char)
  446. PACKINT(OP_SHORT, short)
  447. PACKINT(OP_USHORT, unsigned short)
  448. PACKINT(OP_INT, int)
  449. PACKINT(OP_UINT, unsigned int)
  450. PACKINT(OP_LONG, long)
  451. PACKINT(OP_ULONG, unsigned long)
  452. case ' ':
  453. case ',':
  454. break;
  455. default:
  456. badcode(L, c);
  457. break;
  458. }
  459. }
  460. }
  461. lua_pushinteger(L, write_len);
  462. return 1;
  463. }
  464. #define UNPACKINT(OP, T) \
  465. case OP: \
  466. { \
  467. T a; \
  468. int m = sizeof(a); \
  469. if (i + m > len) \
  470. goto done; \
  471. memcpy(&a, s + i, m); \
  472. i += m; \
  473. doswap(swap, &a, m); \
  474. lua_pushinteger(L, (lua_Integer)a); \
  475. ++n; \
  476. break; \
  477. }
  478. #define UNPACKINT8(OP,T) \
  479. case OP: \
  480. { \
  481. T a; \
  482. int m=sizeof(a); \
  483. if (i+m>len) goto done; \
  484. memcpy(&a,s+i,m); \
  485. i+=m; \
  486. doswap(swap,&a,m); \
  487. int t = (a & 0x80)?(0xffffff00+a):a;\
  488. lua_pushinteger(L,(lua_Integer)t); \
  489. ++n; \
  490. break; \
  491. }
  492. #define UNPACKNUMBER(OP, T) \
  493. case OP: \
  494. { \
  495. T a; \
  496. int m = sizeof(a); \
  497. if (i + m > len) \
  498. goto done; \
  499. memcpy(&a, s + i, m); \
  500. i += m; \
  501. doswap(swap, &a, m); \
  502. lua_pushnumber(L, (lua_Number)a); \
  503. ++n; \
  504. break; \
  505. }
  506. /**
  507. 将一系列数据按照格式字符读取出来(从当前指针位置开始;执行后指针会向后移动)
  508. @api buff:unpack(format)
  509. @string 数据的格式(符号含义见上面pack接口的例子)
  510. @return int 成功读取的数据字节长度
  511. @return any 按格式读出来的数据
  512. @usage
  513. local cnt,a,b,c,s = buff:unpack(">IIHA10") -- 按格式读取几个数据
  514. --如果全部成功读取,cnt就是4+4+2+10=20
  515. */
  516. static int l_zbuff_unpack(lua_State *L)
  517. {
  518. luat_zbuff_t *buff = tozbuff(L);
  519. char *f = (char *)luaL_checkstring(L, 2);
  520. size_t len = buff->len - buff->cursor;
  521. const char *s = (const char*)(buff->addr + buff->cursor);
  522. int i = 0;
  523. int n = 0;
  524. int swap = 0;
  525. lua_pushnil(L); //给个数占位用的
  526. while (*f)
  527. {
  528. int c = *f++;
  529. int N = 1;
  530. if (isdigit(*f))
  531. {
  532. N = 0;
  533. while (isdigit(*f))
  534. N = 10 * N + (*f++) - '0';
  535. if (N == 0 && c == OP_STRING)
  536. {
  537. lua_pushliteral(L, "");
  538. ++n;
  539. }
  540. }
  541. while (N--){
  542. if (!lua_checkstack(L, n))
  543. return luaL_error(L, "too many results to unpack");
  544. switch (c)
  545. {
  546. case OP_LITTLEENDIAN:
  547. case OP_BIGENDIAN:
  548. case OP_NATIVE:
  549. {
  550. swap = doendian(c);
  551. N = 0;
  552. break;
  553. }
  554. case OP_STRING:
  555. {
  556. ++N;
  557. if (i + N > len)
  558. goto done;
  559. lua_pushlstring(L, s + i, N);
  560. i += N;
  561. ++n;
  562. N = 0;
  563. break;
  564. }
  565. UNPACKNUMBER(OP_NUMBER, lua_Number)
  566. UNPACKNUMBER(OP_DOUBLE, double)
  567. UNPACKNUMBER(OP_FLOAT, float)
  568. UNPACKINT8(OP_CHAR, char)
  569. UNPACKINT(OP_BYTE, unsigned char)
  570. UNPACKINT(OP_SHORT, short)
  571. UNPACKINT(OP_USHORT, unsigned short)
  572. UNPACKINT(OP_INT, int)
  573. UNPACKINT(OP_UINT, unsigned int)
  574. UNPACKINT(OP_LONG, long)
  575. UNPACKINT(OP_ULONG, unsigned long)
  576. case ' ':
  577. case ',':
  578. break;
  579. default:
  580. badcode(L, c);
  581. break;
  582. }
  583. }
  584. }
  585. done:
  586. buff->cursor += i;
  587. lua_pushinteger(L, i);
  588. lua_replace(L, -n - 2);
  589. return n + 1;
  590. }
  591. /**
  592. 读取一个指定类型的数据(从当前指针位置开始;执行后指针会向后移动)
  593. @api buff:read类型()
  594. @注释 读取类型可为:I8、U8、I16、U16、I32、U32、I64、U64、F32、F64
  595. @return number 读取的数据,如果越界则为nil
  596. @usage
  597. local data = buff:readI8()
  598. local data = buff:readU32()
  599. */
  600. #define zread(n, t, f) \
  601. static int l_zbuff_read_##n(lua_State *L) \
  602. { \
  603. luat_zbuff_t *buff = tozbuff(L); \
  604. if (buff->len - buff->cursor < sizeof(t)) \
  605. return 0; \
  606. t tmp; \
  607. memcpy(&tmp, buff->addr + buff->cursor, sizeof(t)); \
  608. lua_push##f(L, tmp); \
  609. buff->cursor += sizeof(t); \
  610. return 1; \
  611. }
  612. zread(i8, int8_t, integer);
  613. zread(u8, uint8_t, integer);
  614. zread(i16, int16_t, integer);
  615. zread(u16, uint16_t, integer);
  616. zread(i32, int32_t, integer);
  617. zread(u32, uint32_t, integer);
  618. zread(i64, int64_t, integer);
  619. zread(u64, uint64_t, integer);
  620. zread(f32, float, number);
  621. zread(f64, double, number);
  622. /**
  623. 写入一个指定类型的数据(从当前指针位置开始;执行后指针会向后移动)
  624. @api buff:write类型()
  625. @number 待写入的数据
  626. @注释 写入类型可为:I8、U8、I16、U16、I32、U32、I64、U64、F32、F64
  627. @return number 成功写入的长度
  628. @usage
  629. local len = buff:writeI8(10)
  630. local len = buff:writeU32(1024)
  631. */
  632. #define zwrite(n, t, f) \
  633. static int l_zbuff_write_##n(lua_State *L) \
  634. { \
  635. luat_zbuff_t *buff = tozbuff(L); \
  636. if (buff->len - buff->cursor < sizeof(t)) \
  637. { \
  638. lua_pushinteger(L, 0); \
  639. return 1; \
  640. } \
  641. t tmp = (t)luaL_check##f(L, 2); \
  642. memcpy(buff->addr + buff->cursor, &(tmp), sizeof(t)); \
  643. buff->cursor += sizeof(t); \
  644. lua_pushinteger(L, sizeof(t)); \
  645. return 1; \
  646. }
  647. zwrite(i8, int8_t, integer);
  648. zwrite(u8, uint8_t, integer);
  649. zwrite(i16, int16_t, integer);
  650. zwrite(u16, uint16_t, integer);
  651. zwrite(i32, int32_t, integer);
  652. zwrite(u32, uint32_t, integer);
  653. zwrite(i64, int64_t, integer);
  654. zwrite(u64, uint64_t, integer);
  655. zwrite(f32, float, number);
  656. zwrite(f64, double, number);
  657. /**
  658. 按起始位置和长度取出数据(与当前指针位置无关;执行后指针位置不变)
  659. @api buff:toStr(offset,length)
  660. @int 数据的起始位置(起始位置为0),默认值也是0
  661. @int 数据的长度,默认是全部数据
  662. @return string 读出来的数据
  663. @usage
  664. local s = buff:toStr(0,5)--读取开头的五个字节数据
  665. local s = buff:toStr() -- 取出整个zbuff的数据
  666. local s = buff:toStr(0, buff:used()) -- 取出已使用的部分, 与buff:query()一样
  667. */
  668. static int l_zbuff_toStr(lua_State *L)
  669. {
  670. luat_zbuff_t *buff = tozbuff(L);
  671. int start = luaL_optinteger(L, 2, 0);
  672. if (start > buff->len)
  673. start = buff->len;
  674. int len = luaL_optinteger(L, 3, buff->len);
  675. if (start + len > buff->len)
  676. len = buff->len - start;
  677. lua_pushlstring(L, (const char*)(buff->addr + start), len);
  678. return 1;
  679. }
  680. /**
  681. 获取zbuff对象的长度(与当前指针位置无关;执行后指针位置不变)
  682. @api buff:len()
  683. @return int zbuff对象的长度
  684. @usage
  685. len = buff:len()
  686. len = #buff
  687. */
  688. static int l_zbuff_len(lua_State *L)
  689. {
  690. luat_zbuff_t *buff = tozbuff(L);
  691. lua_pushinteger(L, buff->len);
  692. return 1;
  693. }
  694. /**
  695. 设置buff对象的FrameBuffer属性(与当前指针位置无关;执行后指针位置不变)
  696. @api buff:setFrameBuffer(width,height,bit,color)
  697. @int FrameBuffer的宽度
  698. @int FrameBuffer的高度
  699. @int FrameBuffer的色位深度
  700. @int FrameBuffer的初始颜色
  701. @return bool 设置成功会返回true
  702. @usage
  703. result = buff:setFrameBuffer(320,240,16,0xffff)
  704. */
  705. static int l_zbuff_set_frame_buffer(lua_State *L)
  706. {
  707. luat_zbuff_t *buff = tozbuff(L);
  708. //检查空间够不够
  709. if((luaL_checkinteger(L, 2) * luaL_checkinteger(L, 3) * luaL_checkinteger(L, 4) - 1) / 8 + 1 > buff->len)
  710. return 0;
  711. buff->width = luaL_checkinteger(L,2);
  712. buff->height = luaL_checkinteger(L,3);
  713. buff->bit = luaL_checkinteger(L,4);
  714. if (lua_isinteger(L, 5))
  715. {
  716. LUA_INTEGER color = luaL_checkinteger(L, 5);
  717. uint32_t i;
  718. for (i = 0; i < buff->width * buff->height; i++)
  719. set_framebuffer_point(buff, i, color);
  720. }
  721. lua_pushboolean(L,1);
  722. return 1;
  723. }
  724. /**
  725. 设置或获取FrameBuffer某个像素点的颜色(与当前指针位置无关;执行后指针位置不变)
  726. @api buff:pixel(x,y,color)
  727. @int 与最左边的距离,范围是0~宽度-1
  728. @int 与最上边的距离,范围是0~高度-1
  729. @int 颜色,如果留空则表示获取该位置的颜色
  730. @return any 设置颜色时,设置成功会返回true;读取颜色时,返回颜色的值,读取失败返回nil
  731. @usage
  732. rerult = buff:pixel(0,3,0)
  733. color = buff:pixel(0,3)
  734. */
  735. static int l_zbuff_pixel(lua_State *L)
  736. {
  737. luat_zbuff_t *buff = tozbuff(L);
  738. uint32_t x = luaL_checkinteger(L,2);
  739. uint32_t y = luaL_checkinteger(L,3);
  740. if(x>=buff->width||y>=buff->height)
  741. return 0;
  742. if (lua_isinteger(L, 4))
  743. {
  744. LUA_INTEGER color = luaL_checkinteger(L, 4);
  745. set_framebuffer_point(buff, x + y * buff->width, color);
  746. lua_pushboolean(L,1);
  747. return 1;
  748. }
  749. else
  750. {
  751. lua_pushinteger(L,get_framebuffer_point(buff,x + y * buff->width));
  752. return 1;
  753. }
  754. }
  755. /**
  756. 画一条线(与当前指针位置无关;执行后指针位置不变)
  757. @api buff:drawLine(x1,y1,x2,y2,color)
  758. @int 起始坐标点与最左边的距离,范围是0~宽度-1
  759. @int 起始坐标点与最上边的距离,范围是0~高度-1
  760. @int 结束坐标点与最左边的距离,范围是0~宽度-1
  761. @int 结束坐标点与最上边的距离,范围是0~高度-1
  762. @int 可选,颜色,默认为0
  763. @return bool 画成功会返回true
  764. @usage
  765. rerult = buff:drawLine(0,0,2,3,0xffff)
  766. */
  767. #define abs(n) (n>0?n:-n)
  768. static int l_zbuff_draw_line(lua_State *L)
  769. {
  770. luat_zbuff_t *buff = tozbuff(L);
  771. if(buff->width<=0) return 0;//不是framebuffer数据
  772. uint32_t x0 = luaL_checkinteger(L,2);
  773. uint32_t y0 = luaL_checkinteger(L,3);
  774. uint32_t x1 = luaL_checkinteger(L,4);
  775. uint32_t y1 = luaL_checkinteger(L,5);
  776. uint32_t color = luaL_optinteger(L,6,0);
  777. //代码参考https://blog.csdn.net/qq_43405938/article/details/102700922
  778. int x = x0, y = y0, dx = x1 - x0, dy = y1 - y0;
  779. int max = (abs(dy) > abs(dx)) ? abs(dy) : abs(dx);
  780. int min = (abs(dy) > abs(dx)) ? abs(dx) : abs(dy);
  781. float e = 2 * min - max;
  782. for (int i = 0; i < max; i++)
  783. {
  784. if(x>=0&&y>=0&&x<buff->width&&y<buff->height)
  785. set_framebuffer_point(buff,x+y*buff->width,color);
  786. if (e >= 0)
  787. {
  788. e = e - 2 * max;
  789. (abs(dy) > abs(dx)) ? (dx >= 0 ? x++ : x--) : (dy >= 0 ? y++ : y--);
  790. }
  791. e += 2 * min;
  792. (abs(dy) > abs(dx)) ? (dy >= 0 ? y++ : y--) : (dx >= 0 ? x++ : x--);
  793. }
  794. lua_pushboolean(L,1);
  795. return 1;
  796. }
  797. /**
  798. 画一个矩形(与当前指针位置无关;执行后指针位置不变)
  799. @api buff:drawRect(x1,y1,x2,y2,color,fill)
  800. @int 起始坐标点与最左边的距离,范围是0~宽度-1
  801. @int 起始坐标点与最上边的距离,范围是0~高度-1
  802. @int 结束坐标点与最左边的距离,范围是0~宽度-1
  803. @int 结束坐标点与最上边的距离,范围是0~高度-1
  804. @int 可选,颜色,默认为0
  805. @bool 可选,是否在内部填充,默认nil
  806. @return bool 画成功会返回true
  807. @usage
  808. rerult = buff:drawRect(0,0,2,3,0xffff)
  809. */
  810. #define CHECK0(n,max) if(n<0)n=0;if(n>=max)n=max-1
  811. static int l_zbuff_draw_rectangle(lua_State *L)
  812. {
  813. luat_zbuff_t *buff = tozbuff(L);
  814. if(buff->width<=0) return 0;//不是framebuffer数据
  815. int32_t x1 = (int32_t)luaL_checkinteger(L,2); CHECK0(x1,buff->width);
  816. int32_t y1 = (int32_t)luaL_checkinteger(L,3); CHECK0(y1,buff->height);
  817. int32_t x2 = (int32_t)luaL_checkinteger(L,4); CHECK0(x2,buff->width);
  818. int32_t y2 = (int32_t)luaL_checkinteger(L,5); CHECK0(y2,buff->height);
  819. int32_t color = (int32_t)luaL_optinteger(L,6,0);
  820. uint8_t fill = lua_toboolean(L,7);
  821. int x,y;
  822. int32_t xmax=x1>x2?x1:x2,xmin=x1>x2?x2:x1,ymax=y1>y2?y1:y2,ymin=y1>y2?y2:y1;
  823. if(fill){
  824. for(x=xmin;x<=xmax;x++)
  825. for(y=ymin;y<=ymax;y++)
  826. set_framebuffer_point(buff,x+y*buff->width,color);
  827. }else{
  828. for(x=xmin;x<=xmax;x++){
  829. set_framebuffer_point(buff,x+ymin*buff->width,color);
  830. set_framebuffer_point(buff,x+ymax*buff->width,color);
  831. }
  832. for(y=ymin;y<=ymax;y++){
  833. set_framebuffer_point(buff,xmin+y*buff->width,color);
  834. set_framebuffer_point(buff,xmax+y*buff->width,color);
  835. }
  836. }
  837. lua_pushboolean(L,1);
  838. return 1;
  839. }
  840. /**
  841. 画一个圆形(与当前指针位置无关;执行后指针位置不变)
  842. @api buff:drawCircle(x,y,r,color,fill)
  843. @int **圆心**与最左边的距离,范围是0~宽度-1
  844. @int **圆心**与最上边的距离,范围是0~高度-1
  845. @int 圆的半径
  846. @int 可选,圆的颜色,默认为0
  847. @bool 可选,是否在内部填充,默认nil
  848. @return bool 画成功会返回true
  849. @usage
  850. rerult = buff:drawCircle(15,5,3,0xC)
  851. rerult = buff:drawCircle(15,5,3,0xC,true)
  852. */
  853. #define DRAW_CIRCLE_ALL(buff, xc, yc, x, y, c) \
  854. { \
  855. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  856. set_framebuffer_point(buff, (xc + x) + (yc + y) * buff->width, c); \
  857. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  858. set_framebuffer_point(buff, (xc - x) + (yc + y) * buff->width, c); \
  859. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  860. set_framebuffer_point(buff, (xc + x) + (yc - y) * buff->width, c); \
  861. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  862. set_framebuffer_point(buff, (xc - x) + (yc - y) * buff->width, c); \
  863. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  864. set_framebuffer_point(buff, (xc + y) + (yc + x) * buff->width, c); \
  865. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  866. set_framebuffer_point(buff, (xc - y) + (yc + x) * buff->width, c); \
  867. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  868. set_framebuffer_point(buff, (xc + y) + (yc - x) * buff->width, c); \
  869. if (x >= 0 && y >= 0 && x < buff->width && y < buff->height) \
  870. set_framebuffer_point(buff, (xc - y) + (yc - x) * buff->width, c); \
  871. }
  872. static int l_zbuff_draw_circle(lua_State *L)
  873. {
  874. luat_zbuff_t *buff = tozbuff(L);
  875. if(buff->width<=0) return 0;//不是framebuffer数据
  876. int32_t xc = luaL_checkinteger(L,2);
  877. int32_t yc = luaL_checkinteger(L,3);
  878. int32_t r = luaL_checkinteger(L,4);
  879. int32_t color = luaL_optinteger(L,5,0);
  880. uint8_t fill = lua_toboolean(L,6);
  881. //代码参考https://www.cnblogs.com/wlzy/p/8695226.html
  882. //圆不在可见区域
  883. if (xc + r < 0 || xc - r >= buff->width || yc + r < 0 || yc - r >= buff->height)
  884. return 0;
  885. int x = 0, y = r, yi, d;
  886. d = 3 - 2 * r;
  887. while (x <= y)
  888. {
  889. if (fill)
  890. {
  891. for (yi = x; yi <= y; yi++)
  892. DRAW_CIRCLE_ALL(buff, xc, yc, x, yi, color);
  893. }
  894. else
  895. {
  896. DRAW_CIRCLE_ALL(buff, xc, yc, x, y, color);
  897. }
  898. if (d < 0)
  899. {
  900. d = d + 4 * x + 6;
  901. }
  902. else
  903. {
  904. d = d + 4 * (x - y) + 10;
  905. y--;
  906. }
  907. x++;
  908. }
  909. lua_pushboolean(L,1);
  910. return 1;
  911. }
  912. /**
  913. 以下标形式进行数据读写(与当前指针位置无关;执行后指针位置不变)
  914. @api buff[n]
  915. @int 第几个数据,以0开始的下标(C标准)
  916. @return number 该位置的数据
  917. @usage
  918. buff[0] = 0xc8
  919. local data = buff[0]
  920. */
  921. static int l_zbuff_index(lua_State *L)
  922. {
  923. //luat_zbuff_t **pp = luaL_checkudata(L, 1, LUAT_ZBUFF_TYPE);
  924. // int i;
  925. luaL_getmetatable(L, LUAT_ZBUFF_TYPE);
  926. lua_pushvalue(L, 2);
  927. lua_rawget(L, -2);
  928. if (lua_isnil(L, -1))
  929. {
  930. /* found no method, so get value from userdata. */
  931. luat_zbuff_t *buff = tozbuff(L);
  932. int o = luaL_checkinteger(L, 2);
  933. if (o >= buff->len)
  934. return 0;
  935. lua_pushinteger(L, buff->addr[o]);
  936. return 1;
  937. };
  938. return 1;
  939. }
  940. static int l_zbuff_newindex(lua_State *L)
  941. {
  942. if (lua_isinteger(L, 2))
  943. {
  944. luat_zbuff_t *buff = tozbuff(L);
  945. if (lua_isinteger(L, 2))
  946. {
  947. int o = luaL_checkinteger(L, 2);
  948. int n = luaL_checkinteger(L, 3) % 256;
  949. if (o > buff->len)
  950. return 0;
  951. buff->addr[o] = n;
  952. }
  953. }
  954. return 0;
  955. }
  956. // __gc l_zbuff_gc为zbuff默认gc函数,gc调用时会释放申请内存并gc掉zbuff,下面为用户手动调用注释
  957. /**
  958. 释放zbuff所申请内存 注意:gc时会自动释放zbuff以及zbuff所申请内存,所以通常无需调用此函数,调用前请确认您已清楚此函数用处!调用此函数并不会释放掉zbuff,仅会释放掉zbuff所申请的内存,zbuff需等gc时自动释放!!!
  959. @api buff:free()
  960. @usage
  961. buff:free()
  962. */
  963. static int l_zbuff_gc(lua_State *L)
  964. {
  965. luat_zbuff_t *buff = tozbuff(L);
  966. if (buff->addr){
  967. luat_heap_opt_free(buff->type,buff->addr);
  968. buff->addr = NULL;
  969. buff->len = 0;
  970. buff->used = 0;
  971. }
  972. return 0;
  973. }
  974. int __zbuff_resize(luat_zbuff_t *buff, uint32_t new_size)
  975. {
  976. void *p = luat_heap_opt_realloc(buff->type, buff->addr, new_size?new_size:1);
  977. if (p)
  978. {
  979. buff->addr = p;
  980. buff->len = new_size;
  981. buff->used = (buff->len > buff->used)?buff->used:buff->len;
  982. return 0;
  983. }
  984. else
  985. {
  986. LLOGE("zbuff realloc failed %d -> %d", buff->len, new_size);
  987. return -1;
  988. }
  989. }
  990. /**
  991. 调整zbuff实际分配空间的大小,类似于realloc的效果,new = realloc(old, n),可以扩大或者缩小(如果缩小后len小于了used,那么used=新len)
  992. @api buff:resize(n)
  993. @int 新空间大小
  994. @usage
  995. buff:resize(20)
  996. */
  997. static int l_zbuff_resize(lua_State *L)
  998. {
  999. luat_zbuff_t *buff = tozbuff(L);
  1000. if (lua_isinteger(L, 2))
  1001. {
  1002. uint32_t n = luaL_checkinteger(L, 2);
  1003. __zbuff_resize(buff, n);
  1004. }
  1005. return 0;
  1006. }
  1007. /**
  1008. zbuff动态写数据,类似于memcpy效果,当原有空间不足时动态扩大空间
  1009. @api buff:copy(start, para,...)
  1010. @int 写入buff的起始位置,如果不为数字,则为buff的used,如果小于0,则从used往前数,-1 = used - 1
  1011. @any 写入buff的数据,string或zbuff者时为一个参数,number时可为多个参数
  1012. @return number 数据成功写入的长度
  1013. @usage
  1014. local len = buff:copy(nil, "123") -- 类似于memcpy(&buff[used], "123", 3) used+= 3 从buff开始写入数据,指针相应地往后移动
  1015. local len = buff:copy(0, "123") -- 类似于memcpy(&buff[0], "123", 3) if (used < 3) used = 3 从位置0写入数据,指针有可能会移动
  1016. 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开始,按数值写入多个字节数据
  1017. 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的内容
  1018. local len = buff:copy(5, buff2, 10, 1024) -- 类似于memcpy(&buff[5], &buff2[10], 1024) if (used < (5+1024)) used = (5+1024)
  1019. */
  1020. static int l_zbuff_copy(lua_State *L)
  1021. {
  1022. luat_zbuff_t *buff = tozbuff(L);
  1023. int temp_cursor = luaL_optinteger(L, 2, buff->used);
  1024. if (temp_cursor < 0)
  1025. {
  1026. temp_cursor = buff->used + temp_cursor;
  1027. if (temp_cursor < 0)
  1028. {
  1029. lua_pushinteger(L, 0);
  1030. return 1;
  1031. }
  1032. }
  1033. if (lua_isinteger(L, 3))
  1034. {
  1035. int len = 0;
  1036. int data = 0;
  1037. while (lua_isinteger(L, 3 + len))
  1038. {
  1039. if (temp_cursor > buff->len)
  1040. {
  1041. if (__zbuff_resize(buff, temp_cursor * 2))
  1042. {
  1043. lua_pushinteger(L, len);
  1044. return 1;
  1045. }
  1046. }
  1047. data = luaL_checkinteger(L, 3 + len);
  1048. *(uint8_t *)(buff->addr + temp_cursor) = data % 0x100;
  1049. temp_cursor++;
  1050. len++;
  1051. }
  1052. buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
  1053. lua_pushinteger(L, len);
  1054. return 1;
  1055. }
  1056. else if (lua_isstring(L, 3))
  1057. {
  1058. size_t len;
  1059. const char *data = luaL_checklstring(L, 3, &len);
  1060. if (len + temp_cursor > buff->len) //防止越界
  1061. {
  1062. if (__zbuff_resize(buff, buff->len + len + temp_cursor))
  1063. {
  1064. lua_pushinteger(L, 0);
  1065. return 1;
  1066. }
  1067. }
  1068. memcpy(buff->addr + temp_cursor, data, len);
  1069. temp_cursor = temp_cursor + len;
  1070. buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
  1071. lua_pushinteger(L, len);
  1072. return 1;
  1073. }
  1074. else if (lua_isuserdata(L, 3))
  1075. {
  1076. luat_zbuff_t *copy_buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  1077. uint32_t start = luaL_optinteger(L, 4, 0);
  1078. uint32_t len = luaL_optinteger(L, 5, copy_buff->used);
  1079. if (len + temp_cursor > buff->len) //防止越界
  1080. {
  1081. if (__zbuff_resize(buff, buff->len + len + temp_cursor))
  1082. {
  1083. lua_pushinteger(L, 0);
  1084. return 1;
  1085. }
  1086. }
  1087. memcpy(buff->addr + temp_cursor, copy_buff->addr + start, len);
  1088. temp_cursor += len;
  1089. buff->used = (temp_cursor > buff->used)?temp_cursor:buff->used;
  1090. lua_pushinteger(L, len);
  1091. return 1;
  1092. }
  1093. lua_pushinteger(L, 0);
  1094. return 1;
  1095. }
  1096. /**
  1097. 设置/获取zbuff里最后一个数据位置指针到首地址的偏移量,来表示zbuff内已有有效数据量大小,注意这个不同于分配的空间大小,由于seek()会改变最后一个数据位置指针,因此也会影响到used()返回值。
  1098. @api buff:used()
  1099. @int 最后一个数据位置指针到首地址的偏移量,不能是负数,如果不填则不更改当前值,如果该值超过了buff总量,则自动改为buff总量
  1100. @return int 有效数据量大小
  1101. @usage
  1102. buff:used() --直接返回当前的有效数据量大小
  1103. buff:used(123) --设置当前的有效数据量为123字节,如果buff本身不到123字节,比如120字节,则会改成120,返回值是120
  1104. */
  1105. static int l_zbuff_used(lua_State *L)
  1106. {
  1107. luat_zbuff_t *buff = tozbuff(L);
  1108. if (lua_isinteger(L, 2))
  1109. {
  1110. size_t temp_cursor = luaL_optinteger(L, 2, buff->used);
  1111. if (temp_cursor > buff->len)
  1112. {
  1113. buff->used = buff->len;
  1114. }
  1115. else
  1116. {
  1117. buff->used = temp_cursor;
  1118. }
  1119. }
  1120. lua_pushinteger(L, buff->used);
  1121. return 1;
  1122. }
  1123. /**
  1124. 删除zbuff 0~used范围内的一段数据,注意只是改变了used的值,并不是真的在ram里去清除掉数据
  1125. @api buff:del(offset,length)
  1126. @int 起始位置start, 默认0,如果<0则从used往前数,比如 -1 那么start= used - 1
  1127. @int 长度del_len,默认为used,如果start + del_len数值大于used,会强制调整del_len = used - start
  1128. @usage
  1129. buff:del(1,4) --从位置1开始删除4个字节数据
  1130. buff:del(-1,4) --从位置used-1开始删除4个字节数据,但是这肯定会超过used,所以del_len会调整为1,实际上就是删掉了最后一个字节
  1131. */
  1132. static int l_zbuff_del(lua_State *L)
  1133. {
  1134. luat_zbuff_t *buff = tozbuff(L);
  1135. int start = luaL_optinteger(L, 2, 0);
  1136. if (start < 0)
  1137. {
  1138. start += buff->used;
  1139. if (start < 0)
  1140. {
  1141. return 0;
  1142. }
  1143. }
  1144. if (start >= (int)buff->used)
  1145. return 0;
  1146. uint32_t len = luaL_optinteger(L, 3, buff->used);
  1147. if (start + len > buff->used)
  1148. len = buff->used - start;
  1149. if (!len)
  1150. {
  1151. return 0;
  1152. }
  1153. if ((start + len) == buff->used)
  1154. {
  1155. buff->used = start;
  1156. }
  1157. else
  1158. {
  1159. uint32_t rest = buff->used - len;
  1160. memmove(buff->addr + start, buff->addr + start + len, rest);
  1161. buff->used = rest;
  1162. }
  1163. return 0;
  1164. }
  1165. static uint32_t BytesGetBe32(const void *ptr)
  1166. {
  1167. const uint8_t *p = (const uint8_t *)ptr;
  1168. return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
  1169. }
  1170. static uint32_t BytesGetLe32(const void *ptr)
  1171. {
  1172. const uint8_t *p = (const uint8_t *)ptr;
  1173. return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
  1174. }
  1175. /**
  1176. 按起始位置和长度0~used范围内取出数据,如果是1,2,4,8字节,且填写了isbigend参数,则根据isbigend,issigned,isfloat转换成浮点或者整形
  1177. @api buff:query(offset,length,isbigend,issigned,isfloat)
  1178. @int 数据的起始位置(起始位置为0)
  1179. @int 数据的长度
  1180. @boolean 是否是大端格式,如果为nil,则不会转换,直接字节流输出,false为小端格式,true为大端格式
  1181. @boolean 是否是有符号的,默认为false
  1182. @boolean 是否是浮点型,默认为false
  1183. @return string 读出来的数据,如果取出数据是1,2,4,8字节,且isbigend填写了true或者false,则输出浮点或者整形
  1184. @usage
  1185. local s = buff:query(0,5)--读取开头的五个字节数据
  1186. */
  1187. static int l_zbuff_query(lua_State *L)
  1188. {
  1189. luat_zbuff_t *buff = tozbuff(L);
  1190. int start = luaL_optinteger(L, 2, 0);
  1191. if (start < 0)
  1192. {
  1193. start += buff->used;
  1194. if (start < 0)
  1195. {
  1196. lua_pushnil(L);
  1197. return 1;
  1198. }
  1199. }
  1200. if (start > buff->used)
  1201. start = buff->used;
  1202. uint32_t len = luaL_optinteger(L, 3, buff->used);
  1203. if (start + len > buff->used)
  1204. len = buff->used - start;
  1205. if (!len)
  1206. {
  1207. lua_pushnil(L);
  1208. return 1;
  1209. }
  1210. if (lua_isboolean(L, 4) && (len <= 8))
  1211. {
  1212. int is_bigend = lua_toboolean(L, 4);
  1213. int is_float = 0;
  1214. int is_signed = 0;
  1215. if (lua_isboolean(L, 5))
  1216. {
  1217. is_signed = lua_toboolean(L, 5);
  1218. }
  1219. if (lua_isboolean(L, 6))
  1220. {
  1221. is_float = lua_toboolean(L, 6);
  1222. }
  1223. uint8_t *p = buff->addr + start;
  1224. uint8_t uc;
  1225. int16_t s;
  1226. uint16_t us;
  1227. int32_t i;
  1228. // uint32_t ui;
  1229. int64_t l;
  1230. float f;
  1231. double d;
  1232. switch(len)
  1233. {
  1234. case 1:
  1235. if (is_signed)
  1236. {
  1237. i = (p[0] & 0x80)?(p[0] + 0xffffff00):p[0];
  1238. lua_pushinteger(L, i);
  1239. }
  1240. else
  1241. {
  1242. uc = p[0];
  1243. lua_pushinteger(L, uc);
  1244. }
  1245. break;
  1246. case 2:
  1247. if (is_bigend)
  1248. {
  1249. us = (p[0] << 8) | p[1];
  1250. }
  1251. else
  1252. {
  1253. us = (p[1] << 8) | p[0];
  1254. }
  1255. if (is_signed)
  1256. {
  1257. s = us;
  1258. lua_pushinteger(L, s);
  1259. }
  1260. else
  1261. {
  1262. lua_pushinteger(L, us);
  1263. }
  1264. break;
  1265. case 4:
  1266. if (is_float)
  1267. {
  1268. memcpy(&f, p, len);
  1269. lua_pushnumber(L, f);
  1270. }
  1271. else
  1272. {
  1273. if (is_bigend)
  1274. {
  1275. i = BytesGetBe32(p);
  1276. }
  1277. else
  1278. {
  1279. i = BytesGetLe32(p);
  1280. }
  1281. lua_pushinteger(L, i);
  1282. }
  1283. break;
  1284. case 8:
  1285. if (is_float)
  1286. {
  1287. memcpy(&d, p, len);
  1288. lua_pushnumber(L, d);
  1289. }
  1290. else
  1291. {
  1292. if (is_bigend)
  1293. {
  1294. l = BytesGetBe32(p + 4) | ((int64_t)BytesGetBe32(p) << 32);
  1295. }
  1296. else
  1297. {
  1298. l = BytesGetLe32(p) | ((int64_t)BytesGetLe32(p + 4) << 32);
  1299. }
  1300. lua_pushinteger(L, l);
  1301. }
  1302. break;
  1303. default:
  1304. lua_pushlstring(L, (const char*)(buff->addr + start), len);
  1305. break;
  1306. }
  1307. return 1;
  1308. }
  1309. lua_pushlstring(L, (const char*)(buff->addr + start), len);
  1310. return 1;
  1311. }
  1312. /**
  1313. zbuff的类似于memset操作,类似于memset(&buff[start], num, len),当然有ram越界保护,会对len有一定的限制
  1314. @api buff:set(start, num, len)
  1315. @int 可选,开始位置,默认为0,
  1316. @int 可选,默认为0。要设置为的值
  1317. @int 可选,长度,默认为全部空间,如果超出范围了,会自动截断
  1318. @usage
  1319. -- 全部初始化为0
  1320. buff:set() --等同于 memset(buff, 0, sizeof(buff))
  1321. buff:set(8) --等同于 memset(&buff[8], 0, sizeof(buff) - 8)
  1322. buff:set(0, 0x55) --等同于 memset(buff, 0x55, sizeof(buff))
  1323. buff:set(4, 0xaa, 12) --等用于 memset(&buff[4], 0xaa, 12)
  1324. */
  1325. static int l_zbuff_set(lua_State *L)
  1326. {
  1327. luat_zbuff_t *buff = tozbuff(L);
  1328. int num = luaL_optinteger(L, 3, 0);
  1329. uint32_t start = luaL_optinteger(L, 2, 0);
  1330. uint32_t len = luaL_optinteger(L, 4, buff->len);
  1331. memset(buff->addr + start, num & 0x00ff, ((len + start) > buff->len)?(buff->len - start):len);
  1332. return 0;
  1333. }
  1334. /**
  1335. zbuff的类似于memcmp操作,类似于memcmp(&buff[start], &buff2[start2], len)
  1336. @api buff:isEqual(start, buff2, start2, len)
  1337. @int 可选,开始位置,默认为0,
  1338. @zbuff 比较的对象
  1339. @int 可选,比较的对象的开始位置,默认为0
  1340. @int 比较长度
  1341. @return boolean true相等,false不相等
  1342. @return int 相等返回0,不相等返回第一个不相等位置的序号
  1343. @usage
  1344. local result, offset = buff:isEqual(1, buff2, 2, 10) --等同于memcmp(&buff[1], &buff2[2], 10)
  1345. */
  1346. static int l_zbuff_equal(lua_State *L)
  1347. {
  1348. luat_zbuff_t *buff = tozbuff(L);
  1349. uint32_t offset1 = luaL_optinteger(L, 2, 0);
  1350. luat_zbuff_t *buff2 = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  1351. uint32_t offset2 = luaL_optinteger(L, 4, 0);
  1352. uint32_t len = luaL_optinteger(L, 5, 1);
  1353. uint32_t i;
  1354. uint8_t *b1 = buff->addr + offset1;
  1355. uint8_t *b2 = buff2->addr + offset2;
  1356. for(i = 0; i < len; i++) {
  1357. if (b1[i] != b2[i]) {
  1358. lua_pushboolean(L, 0);
  1359. lua_pushinteger(L, i);
  1360. return 2;
  1361. }
  1362. }
  1363. lua_pushboolean(L, 1);
  1364. lua_pushinteger(L, 0);
  1365. return 2;
  1366. }
  1367. /**
  1368. 将当前zbuff数据转base64,输出到下一个zbuff中
  1369. @api buff:toBase64(dst)
  1370. @userdata zbuff指针
  1371. @return int 转换后的实际长度
  1372. @usage
  1373. -- dst:len必须大于buff:used() * 1.35 + 3, 确保有足够空间存放base64数据
  1374. buff:toBase64(dst)
  1375. */
  1376. #include "luat_str.h"
  1377. static int l_zbuff_to_base64(lua_State *L) {
  1378. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 1, LUAT_ZBUFF_TYPE));
  1379. luat_zbuff_t *buff2 = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  1380. size_t olen = 0;
  1381. int ret = luat_str_base64_encode(buff2->addr, buff2->len, &olen, buff->addr, buff->used);
  1382. if (ret) {
  1383. LLOGE("zbuff toBase64 failed %d", ret);
  1384. lua_pushinteger(L, 0);
  1385. }
  1386. else {
  1387. buff2->used = olen;
  1388. lua_pushinteger(L, olen);
  1389. }
  1390. return 1;
  1391. };
  1392. static const luaL_Reg lib_zbuff[] = {
  1393. {"write", l_zbuff_write},
  1394. {"read", l_zbuff_read},
  1395. {"clear", l_zbuff_clear},
  1396. {"seek", l_zbuff_seek},
  1397. {"pack", l_zbuff_pack},
  1398. {"unpack", l_zbuff_unpack},
  1399. {"get", l_zbuff_index},
  1400. {"readI8", l_zbuff_read_i8},
  1401. {"readI16", l_zbuff_read_i16},
  1402. {"readI32", l_zbuff_read_i32},
  1403. {"readI64", l_zbuff_read_i64},
  1404. {"readU8", l_zbuff_read_u8},
  1405. {"readU16", l_zbuff_read_u16},
  1406. {"readU32", l_zbuff_read_u32},
  1407. {"readU64", l_zbuff_read_u64},
  1408. {"readF32", l_zbuff_read_f32},
  1409. {"readF64", l_zbuff_read_f64},
  1410. {"writeI8", l_zbuff_write_i8},
  1411. {"writeI16", l_zbuff_write_i16},
  1412. {"writeI32", l_zbuff_write_i32},
  1413. {"writeI64", l_zbuff_write_i64},
  1414. {"writeU8", l_zbuff_write_u8},
  1415. {"writeU16", l_zbuff_write_u16},
  1416. {"writeU32", l_zbuff_write_u32},
  1417. {"writeU64", l_zbuff_write_u64},
  1418. {"writeF32", l_zbuff_write_f32},
  1419. {"writeF64", l_zbuff_write_f64},
  1420. {"toStr", l_zbuff_toStr},
  1421. {"len", l_zbuff_len},
  1422. {"setFrameBuffer", l_zbuff_set_frame_buffer},
  1423. {"pixel", l_zbuff_pixel},
  1424. {"drawLine", l_zbuff_draw_line},
  1425. {"drawRect", l_zbuff_draw_rectangle},
  1426. {"drawCircle", l_zbuff_draw_circle},
  1427. //{"__index", l_zbuff_index},
  1428. //{"__len", l_zbuff_len},
  1429. //{"__newindex", l_zbuff_newindex},
  1430. {"free", l_zbuff_gc},
  1431. //以下为扩展用法,数据的增减操作尽量不要和上面的read,write一起使用,对数值指针的用法不一致
  1432. {"copy", l_zbuff_copy},
  1433. {"set", l_zbuff_set},
  1434. {"query",l_zbuff_query},
  1435. {"del", l_zbuff_del},
  1436. {"resize", l_zbuff_resize},
  1437. {"reSize", l_zbuff_resize},
  1438. {"used", l_zbuff_used},
  1439. {"isEqual", l_zbuff_equal},
  1440. {"toBase64", l_zbuff_to_base64},
  1441. {NULL, NULL}};
  1442. static int luat_zbuff_meta_index(lua_State *L) {
  1443. if (lua_isinteger(L, 2)) {
  1444. return l_zbuff_index(L);
  1445. }
  1446. if (lua_isstring(L, 2)) {
  1447. const char* keyname = luaL_checkstring(L, 2);
  1448. //printf("zbuff keyname = %s\n", keyname);
  1449. int i = 0;
  1450. while (1) {
  1451. if (lib_zbuff[i].name == NULL) break;
  1452. if (!strcmp(keyname, lib_zbuff[i].name)) {
  1453. lua_pushcfunction(L, lib_zbuff[i].func);
  1454. return 1;
  1455. }
  1456. i++;
  1457. }
  1458. }
  1459. return 0;
  1460. }
  1461. static void createmeta(lua_State *L)
  1462. {
  1463. luaL_newmetatable(L, LUAT_ZBUFF_TYPE); /* create metatable for file handles */
  1464. // lua_pushvalue(L, -1); /* push metatable */
  1465. // lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
  1466. // luaL_setfuncs(L, lib_zbuff, 0); /* add file methods to new metatable */
  1467. //luaL_setfuncs(L, lib_zbuff_metamethods, 0);
  1468. //luaL_setfuncs(L, lib_zbuff, 0);
  1469. lua_pushcfunction(L, l_zbuff_len);
  1470. lua_setfield(L, -2, "__len");
  1471. lua_pushcfunction(L, l_zbuff_gc);
  1472. lua_setfield(L, -2, "__gc");
  1473. lua_pushcfunction(L, luat_zbuff_meta_index);
  1474. lua_setfield(L, -2, "__index");
  1475. lua_pushcfunction(L, l_zbuff_newindex);
  1476. lua_setfield(L, -2, "__newindex");
  1477. lua_pop(L, 1); /* pop new metatable */
  1478. //luaL_newlib(L, lib_zbuff);
  1479. }
  1480. #include "rotable2.h"
  1481. static const rotable_Reg_t reg_zbuff[] =
  1482. {
  1483. {"create", ROREG_FUNC(l_zbuff_create)},
  1484. //@const SEEK_SET number 以头为基点
  1485. {"SEEK_SET", ROREG_INT(ZBUFF_SEEK_SET)},
  1486. //@const SEEK_CUR number 以当前位置为基点
  1487. {"SEEK_CUR", ROREG_INT(ZBUFF_SEEK_CUR)},
  1488. //@const SEEK_END number 以末尾为基点
  1489. {"SEEK_END", ROREG_INT(ZBUFF_SEEK_END)},
  1490. //@const HEAP_AUTO number 自动申请(如存在psram则在psram进行申请,如不存在或失败则在sram进行申请)
  1491. {"HEAP_AUTO", ROREG_INT(LUAT_HEAP_AUTO)},
  1492. //@const HEAP_SRAM number 在sram申请
  1493. {"HEAP_SRAM", ROREG_INT(LUAT_HEAP_SRAM)},
  1494. //@const HEAP_PSRAM number 在psram申请
  1495. {"HEAP_PSRAM", ROREG_INT(LUAT_HEAP_PSRAM)},
  1496. {NULL, ROREG_INT(0)
  1497. }
  1498. };
  1499. LUAMOD_API int luaopen_zbuff(lua_State *L)
  1500. {
  1501. luat_newlib2(L, reg_zbuff);
  1502. createmeta(L);
  1503. return 1;
  1504. }