Преглед изворни кода

add:bit64数据基础运算库

alienwalker пре 3 година
родитељ
комит
0f64ad276c
3 измењених фајлова са 702 додато и 0 уклоњено
  1. 224 0
      demo/test/use/main.lua
  2. 2 0
      luat/include/luat_libs.h
  3. 476 0
      luat/modules/luat_lib_bit64.c

+ 224 - 0
demo/test/use/main.lua

@@ -0,0 +1,224 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "httpdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要http库, 大部分能联网的设备都具有这个库
+http也是内置库, 无需require
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用http库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+---- MultipartForm上传文件
+-- url string 请求URL地址
+-- req_headers table 请求头
+-- params table 需要传输的数据参数
+local function postMultipartFormData(url, params)
+    local boundary = "----WebKitFormBoundary"..os.time()
+    local req_headers = {
+        ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+    }
+    local body = {}
+
+    -- 解析拼接 body
+    for k,v in pairs(params) do
+        if k=="texts" then
+            local bodyText = ""
+            for kk,vv in pairs(v) do
+                print(kk,vv)
+                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
+            end
+            table.insert(body, bodyText)
+        elseif k=="files" then
+            local contentType =
+            {
+                txt = "text/plain",             -- 文本
+                jpg = "image/jpeg",             -- JPG 格式图片
+                jpeg = "image/jpeg",            -- JPEG 格式图片
+                png = "image/png",              -- PNG 格式图片   
+                gif = "image/gif",              -- GIF 格式图片
+                html = "image/html",            -- HTML
+                json = "application/json"       -- JSON
+            }
+            
+            for kk,vv in pairs(v) do
+                if type(vv) == "table" then
+                    for i=1, #vv do
+                        print(kk,vv[i])
+                        table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv[i]:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv[i]:match("%.(%w+)$")].."\r\n\r\n")
+                        table.insert(body, io.readFile(vv[i]))
+                        table.insert(body, "\r\n")
+                    end
+                else
+                    print(kk,vv)
+                    table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv:match("%.(%w+)$")].."\r\n\r\n")
+                    table.insert(body, io.readFile(vv))
+                    table.insert(body, "\r\n")
+                end
+            end
+        end
+    end 
+    table.insert(body, "--"..boundary.."--\r\n")
+    body = table.concat(body)
+    log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
+    log.info("body: " .. body:len() .. "\r\n" .. body)
+    local code, headers, body = http.request("POST",url,
+            req_headers,
+            body
+    ).wait()   
+    log.info("http.post", code, headers, body)
+end
+
+-- sys.timerLoopStart(function ()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if rtos.bsp():startsWith("ESP32") then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "uiot"
+        local password = "12345678"
+        log.info("wifi", ssid, password)
+        -- TODO 改成esptouch配网
+        LED = gpio.setup(12, 0, gpio.PULLUP)
+        wlan.init()
+        wlan.setMode(wlan.STATION)
+        wlan.connect(ssid, password, 1)
+        local result, data = sys.waitUntil("IP_READY", 30000)
+        log.info("wlan", "IP_READY", result, data)
+        device_id = wlan.getMac()
+    elseif rtos.bsp() == "AIR105" then
+        -- w5500 以太网, 当前仅Air105支持
+        w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
+        w5500.config() --默认是DHCP模式
+        w5500.bind(socket.ETH0)
+        LED = gpio.setup(62, 0, gpio.PULLUP)
+        sys.wait(1000)
+        -- TODO 获取mac地址作为device_id
+    elseif rtos.bsp() == "EC618" then
+        -- Air780E/Air600E系列
+        --mobile.simid(2)
+        LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+        -- log.info("ipv6", mobile.ipv6(true))
+        sys.waitUntil("IP_READY", 30000)
+    end
+
+    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
+    -- if crypto.cipher_suites then
+    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    -- end
+
+    -------------------------------------
+    -------- HTTP 演示代码 --------------
+    -------------------------------------
+
+    
+    socket.sslLog(2)
+    while 1 do
+        -- 最普通的Http GET请求
+        -- local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
+        -- log.info("http.get", code, headers, body)
+        -- local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
+        -- log.info("http.get", code, headers, body)
+        -- sys.wait(100)
+        	
+        
+        log.info("mem.lua", rtos.meminfo())
+        log.info("mem.sys", rtos.meminfo("sys"))
+        local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
+        log.info("http.get", code, headers, #body)
+        sys.wait(100)
+        log.info("mem.lua", rtos.meminfo())
+        log.info("mem.sys", rtos.meminfo("sys"))
+        -- 按需打印
+        -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
+        -- headers是个table, 一般作为调试数据存在
+        -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
+        -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
+
+        -- -- POST request 演示
+        -- local req_headers = {}
+        -- req_headers["Content-Type"] = "application/json"
+        -- local body = json.encode({name="LuatOS"})
+        -- local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date", 
+        --         req_headers,
+        --         body -- POST请求所需要的body, string, zbuff, file均可
+        -- ).wait()
+        -- log.info("http.post", code, headers, body)
+
+        
+        -- -- -- POST multipart/form-data模式 上传文件---手动拼接
+        -- local boundary = "----WebKitFormBoundary"..os.time()
+        -- local req_headers = {
+        --     ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+        -- }
+        -- local body = "--"..boundary.."\r\n"..
+        --              "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
+        --              "\r\nContent-Type: text/plain\r\n\r\n"..
+        --              "1111http_测试一二三四654zacc\r\n"..
+        --              "--"..boundary
+
+        -- log.info("headers: ", "\r\n"..json.encode(req_headers))
+        -- log.info("body: ", "\r\n"..body)
+        -- local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
+        --         req_headers,
+        --         body -- POST请求所需要的body, string, zbuff, file均可
+        -- ).wait()
+        -- log.info("http.post", code, headers, body)
+
+        -- -- 也可用postMultipartFormData(url, params) 上传文件
+        -- postMultipartFormData(
+        --     "http://airtest.openluat.com:2900/uploadFileToStatic",
+        --     {
+        --         -- texts = 
+        --         -- {
+        --         --     ["imei"] = "862991234567890",
+        --         --     ["time"] = "20180802180345"
+        --         -- },
+                
+        --         files =
+        --         {
+        --             ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
+        --         }
+        --     }
+        -- )
+    
+        -- -- POST and download, task内的同步操作
+        -- local opts = {}                 -- 额外的配置项
+        -- opts["dst"] = "/data.bin"       -- 下载路径,可选
+        -- opts["timeout"] = 30            -- 超时时长,单位秒,可选
+        -- opts["adapter"] = socket.ETH0  -- 使用哪个网卡,可选
+        -- local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
+        --         {}, -- 请求所添加的 headers, 可以是nil
+        --         "", 
+        --         opts
+        -- ).wait()
+        -- log.info("http.post", code, headers, body) -- 只返回code和headers
+    
+        -- local f = io.open("/data.bin", "rb")
+        -- if f then
+        --     local data = f:read("*a")
+        --     log.info("fs", "data", data, data:toHex())
+        -- end
+        
+        -- -- GET request, 开个task让它自行执行去吧, 不管执行结果了
+        -- sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
+
+        -- log.info("sys", rtos.meminfo("sys"))
+        -- log.info("lua", rtos.meminfo("lua"))
+        sys.wait(10000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 2 - 0
luat/include/luat_libs.h

@@ -145,4 +145,6 @@ LUAMOD_API int luaopen_errdump( lua_State *L );
 LUAMOD_API int luaopen_profiler( lua_State *L );
 LUAMOD_API int luaopen_fskv( lua_State *L );
 LUAMOD_API int luaopen_max30102( lua_State *L );
+
+LUAMOD_API int luaopen_bit64( lua_State *L );
 #endif

+ 476 - 0
luat/modules/luat_lib_bit64.c

@@ -0,0 +1,476 @@
+/*
+@module  bit64
+@summary 32位系统上对64位数据的基本算术运算和逻辑运算,64位数据用9字节string存储,byte7~byte0存数据,byte8=0表示整形,其他表示浮点
+@version 0.1
+@date    2023.03.11
+@video
+@tag LUAT_USE_BIT64
+@demo  bit64
+*/
+#include "luat_base.h"
+#include "luat_malloc.h"
+#define LUAT_LOG_TAG "bit64"
+#include "luat_log.h"
+#define D64_FLAG 0x01
+/**
+64bit数据转成32bit输出
+@api bit64.to32(data64bit)
+@string 9字节数据
+@return int or number
+ */
+static int l_bit64_to32(lua_State *L)
+{
+	double d64;
+	int64_t i64;
+    size_t len;
+    const char *data = luaL_checklstring(L, 1, &len);
+
+    if (len != 9)
+    {
+    	lua_pushnil(L);
+    }
+    if (data[8])
+    {
+        memcpy(&d64, data, 8);
+        lua_pushnumber(L, (lua_Number)d64);
+    }
+    else
+    {
+    	memcpy(&i64, data, 8);
+    	lua_pushinteger(L, (lua_Integer)i64);
+    }
+    return 1;
+}
+
+/**
+32bit数据转成64bit数据
+@api bit64.to64(data32bit)
+@int/number 32bit数据
+@return string 9字节数据
+ */
+static int l_bit64_to64(lua_State *L)
+{
+	double d64;
+	uint64_t u64;
+	uint8_t data[9] = {0};
+	if (lua_isinteger(L, 1))
+	{
+		u64 = (lua_Unsigned)lua_tointeger(L, 1);
+		memcpy(data, &u64, 8);
+	}
+	else if (lua_isnumber(L, 1))
+	{
+		d64 = lua_tonumber(L, 1);
+		data[8] = D64_FLAG;
+		memcpy(data, &d64, 8);
+
+	}
+	lua_pushlstring(L, data, 9);
+	return 1;
+}
+
+/**
+64bit数据格式化打印成字符串,用于显示值
+@api bit64.show(a,type,flag)
+@string a
+@int 进制,10=10进制,16=16进制,默认10,只支持10或者16
+@boolean 整形是否按照无符号方式打印,true是,false不是,默认false,浮点忽略
+@return string 可以打印的值
+ */
+static int l_bit64_show(lua_State *L)
+{
+	int64_t i64;
+	double d64;
+    size_t len;
+    uint8_t data[64] = {0};
+    uint8_t flag = 0;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	lua_pushnil(L);
+    	return 1;
+    }
+    if (string[8])
+    {
+    	memcpy(&d64, string, 8);
+    }
+    else
+    {
+    	memcpy(&i64, string, 8);
+    }
+    uint8_t type = luaL_optinteger(L, 2, 10);
+	if (lua_isboolean(L, 3))
+	{
+		flag = lua_toboolean(L, 3);
+	}
+	if (type != 16)
+	{
+		if (string[8])
+		{
+			len = snprintf_(data, 63, "%f", d64);
+		}
+		else
+		{
+			if (flag)
+			{
+				len = snprintf_(data, 63, "%llu", i64);
+			}
+			else
+			{
+				len = snprintf_(data, 63, "%lld", (uint64_t)i64);
+			}
+		}
+	}
+	else
+	{
+		if (string[8])
+		{
+			len = snprintf_(data, 63, "0x%llx", d64);
+		}
+		else
+		{
+			len = snprintf_(data, 63, "0x%llx", i64);
+		}
+	}
+	lua_pushlstring(L, data, len);
+	return 1;
+}
+
+static int l_bit64_calculate(lua_State *L, uint8_t op)
+{
+	double d64_a,d64_b;
+	int64_t i64_a, i64_b;
+	uint64_t u64;
+    size_t len;
+    uint8_t data[9] = {0};
+    uint8_t flag1 = 0;
+    uint8_t flag2 = 0;
+    uint8_t fa,fb;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	goto DONE;
+    }
+    fa = string[8];
+    if (fa)
+    {
+    	memcpy(&d64_a, string, 8);
+    }
+    else
+    {
+    	memcpy(&i64_a, string, 8);
+    }
+	if (lua_isinteger(L, 2))
+	{
+		i64_b = lua_tointeger(L, 2);
+		fb = 0;
+	}
+	else if (lua_isnumber(L, 2))
+	{
+		d64_b = lua_tonumber(L, 2);
+		fb = 1;
+	}
+	else
+	{
+		string = luaL_checklstring(L, 2, &len);
+	    if (len != 9)
+	    {
+	    	goto DONE;
+	    }
+	    fb = string[8];
+	    if (fb)
+	    {
+	    	memcpy(&d64_b, string, 8);
+	    }
+	    else
+	    {
+	    	memcpy(&i64_b, string, 8);
+	    }
+	}
+
+	if (lua_isboolean(L, 3))
+	{
+		flag1 = lua_toboolean(L, 3);
+	}
+	if (lua_isboolean(L, 4))
+	{
+		flag2 = lua_toboolean(L, 4);
+	}
+	switch(op)
+	{
+	case 0:
+		if (fa && fb)
+		{
+			d64_a = d64_a + d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a + i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a + d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a + (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a + i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 1:
+		if (fa && fb)
+		{
+			d64_a = d64_a - d64_b;
+			goto FLOAT_OP;
+		}
+
+		if (fa && !fb)
+		{
+			d64_a = d64_a - i64_b;
+			goto FLOAT_OP;
+		}
+
+		if (!fa && fb)
+		{
+			d64_a = i64_a - d64_b;
+			goto FLOAT_OP;
+		}
+
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a - (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a - i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 2:
+		if (fa && fb)
+		{
+			d64_a = d64_a * d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a * i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a * d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a * (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a * i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 3:
+		if (fa && fb)
+		{
+			d64_a = d64_a / d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a / i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a / d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a / (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a / i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	}
+FLOAT_OP:
+	if (flag2)
+	{
+		i64_a = d64_a;
+		memcpy(data, &i64_a, 8);
+	}
+	else
+	{
+		data[8] = D64_FLAG;
+		memcpy(data, &d64_a, 8);
+	}
+	goto DONE;
+DONE:
+	lua_pushlstring(L, data, 9);
+	return 1;
+}
+
+/**
+64bit数据加,a+b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.plus(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_plus(lua_State *L)
+{
+	return l_bit64_calculate(L, 0);
+}
+
+
+/**
+64bit数据减,a-b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.minus(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_minus(lua_State *L)
+{
+	return l_bit64_calculate(L, 1);
+}
+
+/**
+64bit数据乘,a*b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.mult(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_multiply(lua_State *L)
+{
+	return l_bit64_calculate(L, 2);
+}
+
+/**
+64bit数据除,a/b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.pide(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_pide(lua_State *L)
+{
+	return l_bit64_calculate(L, 3);
+}
+
+/**
+64bit数据位移 a>>b 或者 a<<b
+@api bit64.pide(a,b,flag)
+@string a
+@int b
+@boolean 位移方向,true左移<<,false右移>>,默认false
+@return string 9字节数据
+ */
+static int l_bit64_shift(lua_State *L)
+{
+	uint64_t u64;
+	uint32_t pos = 0;
+    size_t len;
+    uint8_t data[9] = {0};
+    uint8_t flag = 0;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	goto DONE;
+    }
+    data[8] = string[8];
+    memcpy(&u64, string, 8);
+
+	if (lua_isinteger(L, 2))
+	{
+		pos = lua_tointeger(L, 2);
+		if (!pos)
+		{
+			goto DONE;
+		}
+	}
+	else
+	{
+		goto DONE;
+	}
+	if (lua_isboolean(L, 3))
+	{
+		flag = lua_toboolean(L, 3);
+	}
+	if (flag)
+	{
+		u64 = u64 << pos;
+	}
+	else
+	{
+		u64 = u64 >> pos;
+	}
+    data[8] = string[8];
+    memcpy(data, &u64, 8);
+	lua_pushlstring(L, data, 9);
+	return 1;
+DONE:
+	lua_pushlstring(L, string, len);
+	return 1;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_bit64[] = {
+	{"to32", ROREG_FUNC(l_bit64_to32)},
+	{"to64", ROREG_FUNC(l_bit64_to64)},
+	{"plus", ROREG_FUNC(l_bit64_plus)},
+	{"minus", ROREG_FUNC(l_bit64_minus)},
+	{"multi", ROREG_FUNC(l_bit64_multiply)},
+	{"pide", ROREG_FUNC(l_bit64_pide)},
+	{"shift", ROREG_FUNC(l_bit64_shift)},
+	{"show", ROREG_FUNC(l_bit64_show)},
+	{NULL,       ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_bit64(lua_State *L)
+{
+    luat_newlib2(L, reg_bit64);
+    return 1;
+}