@ -0,0 +1,13 @@ | |||
package luaInGo | |||
import lua "github.com/yuin/gopher-lua" | |||
const ( | |||
InitPoolSize = 128 | |||
NaxPoolSize = 512 | |||
) | |||
//初始化lua LState连接池 | |||
var LuaStatePool = &lStatePool{ | |||
saved: make([]*lua.LState, 0, InitPoolSize), | |||
} |
@ -0,0 +1,75 @@ | |||
package luaInGo | |||
import ( | |||
"fmt" | |||
"io/ioutil" | |||
"os" | |||
"path" | |||
) | |||
// LuaFile lua文件 | |||
type LuaFile struct { | |||
FileName string | |||
} | |||
// LuaFileExist 判断某lua脚本是否存在 | |||
func LuaFileExist(fileName string) bool { | |||
fileList := GetAllLuaFile() | |||
for _, file := range fileList { | |||
if file.FileName == fileName { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
// GetAllLuaFile 获取所有文件 | |||
func GetAllLuaFile() []LuaFile { | |||
// 声明一个文件列表切片 | |||
var fileList []LuaFile | |||
rd, err := ioutil.ReadDir("luafile") | |||
if err != nil { | |||
fmt.Println("GetAllLuaFile error", err) | |||
return fileList | |||
} | |||
for _, fi := range rd { | |||
fileList = append(fileList, LuaFile{fi.Name()}) | |||
} | |||
return fileList | |||
} | |||
// DeleteLuaFile 删除文件 | |||
func DeleteLuaFile(fileName string) bool { | |||
err := os.Remove("luafile/" + fileName) | |||
if err != nil { | |||
fmt.Println("DeleteLuaFile error", err) | |||
return false | |||
} | |||
return true | |||
} | |||
func ListLuaFile(folder string, luas []string) { | |||
files, _ := ioutil.ReadDir(folder) | |||
for _, file := range files { | |||
if file.IsDir() { | |||
ListLuaFile(folder+"/"+file.Name(), luas) | |||
} else { | |||
var filenameWithSuffix string = path.Base(file.Name()) //获取文件名带后缀 | |||
var fileSuffix string = path.Ext(filenameWithSuffix) //获取文件后缀 | |||
if fileSuffix == ".lua" { | |||
filePath := fmt.Sprintf("%s%s%s", folder, "/", file.Name()) | |||
luas = append(luas, filePath) | |||
} | |||
} | |||
} | |||
} | |||
func GetFileModtime(file string) (int64, error) { | |||
stat, err := os.Stat(file) | |||
if err != nil { | |||
fmt.Printf("stat fail, file=%v err=%v", file, err) | |||
return 0, err | |||
} | |||
return stat.ModTime().Unix(), nil | |||
} |
@ -0,0 +1,8 @@ | |||
module luaInGo | |||
go 1.14 | |||
require ( | |||
github.com/vadv/gopher-lua-libs v0.1.0 | |||
github.com/yuin/gopher-lua v0.0.0-20200603152657-dc2b0ca8b37e | |||
) |
@ -0,0 +1,18 @@ | |||
## Usage | |||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/crypto | |||
```lua | |||
local crypto = require("crypto") | |||
-- md5 | |||
if not(crypto.md5("1\n") == "b026324c6904b2a9cb4b88d6d61c81d1") then | |||
error("md5") | |||
end | |||
-- sha256 | |||
if not(crypto.sha256("1\n") == "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865") then | |||
error("sha256") | |||
end | |||
``` | |||
@ -0,0 +1,23 @@ | |||
package crypto | |||
import ( | |||
"crypto/md5" | |||
"crypto/sha256" | |||
"fmt" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func MD5(L *lua.LState) int { | |||
str := L.CheckString(1) | |||
hash := md5.Sum([]byte(str)) | |||
L.Push(lua.LString(fmt.Sprintf("%x", hash))) | |||
return 1 | |||
} | |||
func SHA256(L *lua.LState) int { | |||
str := L.CheckString(1) | |||
hash := sha256.Sum256([]byte(str)) | |||
L.Push(lua.LString(fmt.Sprintf("%x", hash))) | |||
return 1 | |||
} |
@ -0,0 +1,20 @@ | |||
package crypto | |||
import ( | |||
"io/ioutil" | |||
"testing" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func TestApi(t *testing.T) { | |||
data, err := ioutil.ReadFile("../testScript/test_crypto_api.lua") | |||
if err != nil { | |||
t.Fatalf("%s\n", err.Error()) | |||
} | |||
state := lua.NewState() | |||
PreLoadGo(state) | |||
if err := state.DoString(string(data)); err != nil { | |||
t.Fatalf("execute test: %s\n", err.Error()) | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
package crypto | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func PreLoadGo(L *lua.LState) { | |||
L.PreloadModule("crypto", Loader) | |||
} | |||
func Loader(L *lua.LState) int { | |||
t := L.NewTable() | |||
L.SetFuncs(t, api) | |||
L.Push(t) | |||
return 1 | |||
} | |||
var api = map[string]lua.LGFunction{ | |||
"md5": MD5, | |||
"sha256": SHA256, | |||
} |
@ -0,0 +1,70 @@ | |||
package goApis | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
cloudwatch "github.com/vadv/gopher-lua-libs/aws/cloudwatch" | |||
cert_util "github.com/vadv/gopher-lua-libs/cert_util" | |||
chef "github.com/vadv/gopher-lua-libs/chef" | |||
cmd "github.com/vadv/gopher-lua-libs/cmd" | |||
crypto "github.com/vadv/gopher-lua-libs/crypto" | |||
db "github.com/vadv/gopher-lua-libs/db" | |||
filepath "github.com/vadv/gopher-lua-libs/filepath" | |||
goos "github.com/vadv/gopher-lua-libs/goos" | |||
http "github.com/vadv/gopher-lua-libs/http" | |||
humanize "github.com/vadv/gopher-lua-libs/humanize" | |||
inspect "github.com/vadv/gopher-lua-libs/inspect" | |||
ioutil "github.com/vadv/gopher-lua-libs/ioutil" | |||
json "github.com/vadv/gopher-lua-libs/json" | |||
log "github.com/vadv/gopher-lua-libs/log" | |||
plugin "github.com/vadv/gopher-lua-libs/plugin" | |||
pprof "github.com/vadv/gopher-lua-libs/pprof" | |||
prometheus "github.com/vadv/gopher-lua-libs/prometheus/client" | |||
regexp "github.com/vadv/gopher-lua-libs/regexp" | |||
runtime "github.com/vadv/gopher-lua-libs/runtime" | |||
"github.com/vadv/gopher-lua-libs/stats" | |||
storage "github.com/vadv/gopher-lua-libs/storage" | |||
strings "github.com/vadv/gopher-lua-libs/strings" | |||
tac "github.com/vadv/gopher-lua-libs/tac" | |||
tcp "github.com/vadv/gopher-lua-libs/tcp" | |||
telegram "github.com/vadv/gopher-lua-libs/telegram" | |||
template "github.com/vadv/gopher-lua-libs/template" | |||
time "github.com/vadv/gopher-lua-libs/time" | |||
xmlpath "github.com/vadv/gopher-lua-libs/xmlpath" | |||
yaml "github.com/vadv/gopher-lua-libs/yaml" | |||
zabbix "github.com/vadv/gopher-lua-libs/zabbix" | |||
) | |||
// 这里封装一个函数 统一load go中提供给lua调用的函数 | |||
func PreLoadLibs(L *lua.LState) { | |||
time.Preload(L) | |||
strings.Preload(L) | |||
filepath.Preload(L) | |||
ioutil.Preload(L) | |||
http.Preload(L) | |||
regexp.Preload(L) | |||
tac.Preload(L) | |||
inspect.Preload(L) | |||
yaml.Preload(L) | |||
plugin.Preload(L) | |||
cmd.Preload(L) | |||
json.Preload(L) | |||
tcp.Preload(L) | |||
xmlpath.Preload(L) | |||
db.Preload(L) | |||
cert_util.Preload(L) | |||
runtime.Preload(L) | |||
telegram.Preload(L) | |||
zabbix.Preload(L) | |||
pprof.Preload(L) | |||
prometheus.Preload(L) | |||
crypto.Preload(L) | |||
goos.Preload(L) | |||
storage.Preload(L) | |||
humanize.Preload(L) | |||
chef.Preload(L) | |||
template.Preload(L) | |||
cloudwatch.Preload(L) | |||
log.Preload(L) | |||
stats.Preload(L) | |||
} |
@ -0,0 +1,23 @@ | |||
# json | |||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/json | |||
## Usage | |||
```lua | |||
local json = require("json") | |||
-- json.encode() | |||
local jsonString = [[ | |||
{ | |||
"a": {"b":1} | |||
} | |||
]] | |||
local result, err = json.decode(jsonString) | |||
if err then error(err) end | |||
-- json.decode() | |||
local table = {a={b=1}} | |||
local result, err = json.encode(table) | |||
if err then error(err) end | |||
``` |
@ -0,0 +1,31 @@ | |||
package json | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func Decode(L *lua.LState) int { | |||
str := L.CheckString(1) | |||
value, err := ValueDecode(L, []byte(str)) | |||
if err != nil { | |||
L.Push(lua.LNil) | |||
L.Push(lua.LString(err.Error())) | |||
return 2 | |||
} | |||
L.Push(value) | |||
return 1 | |||
} | |||
func Encode(L *lua.LState) int { | |||
value := L.CheckAny(1) | |||
data, err := ValueEncode(value) | |||
if err != nil { | |||
L.Push(lua.LNil) | |||
L.Push(lua.LString(err.Error())) | |||
return 2 | |||
} | |||
L.Push(lua.LString(string(data))) | |||
return 1 | |||
} |
@ -0,0 +1,15 @@ | |||
package json | |||
import ( | |||
"testing" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func TestApi(t *testing.T) { | |||
state := lua.NewState() | |||
PreloadGo(state) | |||
if err := state.DoFile("../testScript/test_json_api.lua"); err != nil { | |||
t.Fatalf("execute test: %s\n", err.Error()) | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
package json | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func PreloadGo(L *lua.LState) { | |||
L.PreloadModule("json", Loader) | |||
} | |||
func Loader(L *lua.LState) int { | |||
t := L.NewTable() | |||
L.SetFuncs(t, api) | |||
L.Push(t) | |||
return 1 | |||
} | |||
var api = map[string]lua.LGFunction{ | |||
"decode": Decode, | |||
"encode": Encode, | |||
} |
@ -0,0 +1,127 @@ | |||
package json | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
var ( | |||
errNested = errors.New("cannot encode recursively nested tables to JSON") | |||
errSparseArray = errors.New("cannot encode sparse array") | |||
errInvalidKeys = errors.New("cannot encode mixed or invalid key types") | |||
) | |||
type invalidTypeError lua.LValueType | |||
func (i invalidTypeError) Error() string { | |||
return `cannot encode ` + lua.LValueType(i).String() + ` to JSON` | |||
} | |||
type jsonValue struct { | |||
lua.LValue | |||
visited map[*lua.LTable]bool | |||
} | |||
func (j jsonValue) MarshalJSON() (data []byte, err error) { | |||
switch converted := j.LValue.(type) { | |||
case lua.LBool: | |||
data, err = json.Marshal(bool(converted)) | |||
case lua.LNumber: | |||
data, err = json.Marshal(float64(converted)) | |||
case *lua.LNilType: | |||
data = []byte(`null`) | |||
case lua.LString: | |||
data, err = json.Marshal(string(converted)) | |||
case *lua.LTable: | |||
if j.visited[converted] { | |||
return nil, errNested | |||
} | |||
j.visited[converted] = true | |||
key, value := converted.Next(lua.LNil) | |||
switch key.Type() { | |||
case lua.LTNil: // empty table | |||
data = []byte(`[]`) | |||
case lua.LTNumber: | |||
arr := make([]jsonValue, 0, converted.Len()) | |||
expectedKey := lua.LNumber(1) | |||
for key != lua.LNil { | |||
if key.Type() != lua.LTNumber { | |||
err = errInvalidKeys | |||
return | |||
} | |||
if expectedKey != key { | |||
err = errSparseArray | |||
return | |||
} | |||
arr = append(arr, jsonValue{value, j.visited}) | |||
expectedKey++ | |||
key, value = converted.Next(key) | |||
} | |||
data, err = json.Marshal(arr) | |||
case lua.LTString: | |||
obj := make(map[string]jsonValue) | |||
for key != lua.LNil { | |||
if key.Type() != lua.LTString { | |||
err = errInvalidKeys | |||
return | |||
} | |||
obj[key.String()] = jsonValue{value, j.visited} | |||
key, value = converted.Next(key) | |||
} | |||
data, err = json.Marshal(obj) | |||
default: | |||
err = errInvalidKeys | |||
} | |||
default: | |||
err = invalidTypeError(j.LValue.Type()) | |||
} | |||
return | |||
} | |||
// ValueDecode converts the JSON encoded data to Lua values. | |||
func ValueDecode(L *lua.LState, data []byte) (lua.LValue, error) { | |||
var value interface{} | |||
err := json.Unmarshal(data, &value) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return decode(L, value), nil | |||
} | |||
func decode(L *lua.LState, value interface{}) lua.LValue { | |||
switch converted := value.(type) { | |||
case bool: | |||
return lua.LBool(converted) | |||
case float64: | |||
return lua.LNumber(converted) | |||
case string: | |||
return lua.LString(converted) | |||
case []interface{}: | |||
arr := L.CreateTable(len(converted), 0) | |||
for _, item := range converted { | |||
arr.Append(decode(L, item)) | |||
} | |||
return arr | |||
case map[string]interface{}: | |||
tbl := L.CreateTable(0, len(converted)) | |||
for key, item := range converted { | |||
tbl.RawSetH(lua.LString(key), decode(L, item)) | |||
} | |||
return tbl | |||
case nil: | |||
return lua.LNil | |||
} | |||
panic("unreachable") | |||
} | |||
// ValueEncode returns the JSON encoding of value. | |||
func ValueEncode(value lua.LValue) ([]byte, error) { | |||
return json.Marshal(jsonValue{ | |||
LValue: value, | |||
visited: make(map[*lua.LTable]bool), | |||
}) | |||
} |
@ -0,0 +1,30 @@ | |||
# strings | |||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/strings | |||
## Usage | |||
```lua | |||
local strings = require("strings") | |||
-- strings.split(string, sep) | |||
local result = strings.split("a b c d", " ") | |||
-- Output: { "a", "b", "c", "d" } | |||
-- strings.has_prefix(string, prefix) | |||
local result = strings.has_prefix("abcd", "a") | |||
-- Output: true | |||
-- strings.has_suffix(string, suffix) | |||
local result = strings.has_suffix("abcd", "d") | |||
-- Output: true | |||
-- strings.trim(string, cutset) | |||
local result = strings.trim("abcd", "d") | |||
-- Output: abc | |||
-- strings.contains(string, substring) | |||
local result = strings.contains("abcd", "d") | |||
-- Output: true | |||
``` | |||
@ -0,0 +1,74 @@ | |||
package strings | |||
import ( | |||
"strings" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
// Split(): lua strings.split(string, sep): port of go string.Split() returns table | |||
func Split(L *lua.LState) int { | |||
str := L.CheckString(1) | |||
delim := L.CheckString(2) | |||
strSlice := strings.Split(str, delim) | |||
result := L.CreateTable(len(strSlice), 0) | |||
for _, str := range strSlice { | |||
result.Append(lua.LString(str)) | |||
} | |||
L.Push(result) | |||
return 1 | |||
} | |||
// HasPrefix(): lua strings.has_prefix(string, suffix): port of go string.HasPrefix() return bool | |||
func HasPrefix(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.HasPrefix(str1, str2) | |||
L.Push(lua.LBool(result)) | |||
return 1 | |||
} | |||
// HasSuffix(): lua strings.has_suffix(string, prefix): port of go string.HasSuffix() returns bool | |||
func HasSuffix(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.HasSuffix(str1, str2) | |||
L.Push(lua.LBool(result)) | |||
return 1 | |||
} | |||
// Trim(): lua strings.trim(string, cutset) Port of go string.Trim() returns string | |||
func Trim(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.Trim(str1, str2) | |||
L.Push(lua.LString(result)) | |||
return 1 | |||
} | |||
// TrimPrefix(): lua strings.trim_prefix(string, cutset) Port of go string.TrimPrefix() returns string | |||
func TrimPrefix(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.TrimPrefix(str1, str2) | |||
L.Push(lua.LString(result)) | |||
return 1 | |||
} | |||
// TrimSuffix(): lua strings.trim_suffix(string, cutset) Port of go string.TrimSuffix() returns string | |||
func TrimSuffix(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.TrimSuffix(str1, str2) | |||
L.Push(lua.LString(result)) | |||
return 1 | |||
} | |||
// Contains(): lua strings.contains(string, cutset) Port of go string.Contains() returns bool | |||
func Contains(L *lua.LState) int { | |||
str1 := L.CheckString(1) | |||
str2 := L.CheckString(2) | |||
result := strings.Contains(str1, str2) | |||
L.Push(lua.LBool(result)) | |||
return 1 | |||
} |
@ -0,0 +1,15 @@ | |||
package strings | |||
import ( | |||
"testing" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func TestApi(t *testing.T) { | |||
state := lua.NewState() | |||
PreLoadGo(state) | |||
if err := state.DoFile("../testScript/test_strings_api.lua"); err != nil { | |||
t.Fatalf("execute test: %s\n", err.Error()) | |||
} | |||
} |
@ -0,0 +1,26 @@ | |||
package strings | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func PreLoadGo(L *lua.LState) { | |||
L.PreloadModule("strings", Loader) | |||
} | |||
func Loader(L *lua.LState) int { | |||
t := L.NewTable() | |||
L.SetFuncs(t, api) | |||
L.Push(t) | |||
return 1 | |||
} | |||
var api = map[string]lua.LGFunction{ | |||
"split": Split, | |||
"trim": Trim, | |||
"trim_prefix": TrimPrefix, | |||
"trim_suffix": TrimSuffix, | |||
"has_prefix": HasPrefix, | |||
"has_suffix": HasSuffix, | |||
"contains": Contains, | |||
} |
@ -0,0 +1,4 @@ | |||
local crypto = require("crypto") | |||
if not(crypto.md5("1\n") == "b026324c6904b2a9cb4b88d6d61c81d1") then error("md5") end | |||
if not(crypto.sha256("1\n") == "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865") then error("sha256") end |
@ -0,0 +1,14 @@ | |||
local json = require("json") | |||
local jsonStringWithNull = [[{"a":{"b":1, "c":null}}]] | |||
local jsonString = [[{"a":{"b":1}}]] | |||
local result, err = json.decode(jsonStringWithNull) | |||
if err then error(err) end | |||
if not(result["a"]["b"] == 1) then error("must be decode") end | |||
print("done: json.decode()") | |||
local result, err = json.encode(result) | |||
if err then error(err) end | |||
if not(result==jsonString) then error("must be encode "..result) end | |||
print("done: json.encode()") |
@ -0,0 +1,26 @@ | |||
local strings = require("strings") | |||
local str = "hello world" | |||
local t = strings.split(str, " ") | |||
local count_t = 0 | |||
for k, v in pairs(t) do | |||
count_t = count_t + 1 | |||
if k == 1 then if not(v == "hello") then error("strings.split()") end end | |||
if k == 2 then if not(v == "world") then error("strings.split()") end end | |||
end | |||
if not(count_t == 2) then error("string.split()") end | |||
print("done: strings.split()") | |||
if not(strings.has_prefix(str, "hello")) then error("strings.has_prefix()") end | |||
if not(strings.has_suffix(str, "world")) then error("strings.has_suffix()") end | |||
print("done: strings.has_suffix, strings.has_prefix") | |||
if not(strings.trim(str, "world") == "hello ") then error("strings.trim()") end | |||
if not(strings.trim(str, "hello ") == "world") then error("strings.trim()") end | |||
if not(strings.trim_prefix(str, "hello ") == "world") then error("strings.trim()") end | |||
if not(strings.trim_suffix(str, "hello ") == "hello world") then error("strings.trim()") end | |||
print("done: strings.trim()") | |||
if not(strings.contains(str, "hello ") == true) then error("strings.contains()") end | |||
print("done: strings.contains()") |
@ -0,0 +1,24 @@ | |||
local time = require("time") | |||
local lua_before = os.clock() | |||
local before = time.unix() | |||
time.sleep(2) | |||
local after = time.unix() | |||
local lua_after = os.clock() | |||
if after - before < 1 then error("time.unix()") end | |||
if lua_after - lua_before < 2 then error("time.sleep()") end | |||
print("done: time.sleep(), time.unix()") | |||
local parse, err = time.parse("Dec 2 03:33:05 2018", "Jan 2 15:04:05 2006") | |||
if err then error(err) end | |||
if not(parse == 1543721585) then error("time.parse(): 1") end | |||
print("done: time.parse(): 1") | |||
local _, err = time.parse("Dec 32 03:33:05 2018", "Jan 2 15:04:05 2006") | |||
if (err == nil) then error("time.parse(): must be error") end | |||
print("done: time.parse(): 2") | |||
local result, err = time.format(1543721585, "Jan 2 15:04:05 2006", "Europe/Moscow") | |||
if err then error(err) end | |||
if not(result == "Dec 2 06:33:05 2018") then error("time.format()") end | |||
print("done: time.format(): 1") |
@ -0,0 +1,28 @@ | |||
# time | |||
origin code: https://github.com/vadv/gopher-lua-libs/tree/master/time | |||
## Usage | |||
```lua | |||
local time = require("time") | |||
-- time.unix(), time.sleep() | |||
local begin = time.unix() | |||
time.sleep(1.2) | |||
local stop = time.unix() | |||
local result = stop - begin | |||
result = math.floor(result * 10^2 + 0.5) / 10^2 | |||
if not(result == 1) then error("time.sleep()") end | |||
-- time.parse(value, layout) | |||
local result, err = time.parse("Dec 2 03:33:05 2018", "Jan 2 15:04:05 2006") | |||
if err then error(err) end | |||
if not(result == 1543721585) then error("time.parse()") end | |||
-- time.format(value, layout, location) | |||
local result, err = time.format(1543721585, "Jan 2 15:04:05 2006", "Europe/Moscow") | |||
if err then error(err) end | |||
if not(result == "Dec 2 06:33:05 2018") then error("time.format()") end | |||
``` | |||
@ -0,0 +1,62 @@ | |||
package time | |||
import ( | |||
"time" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func Unix(L *lua.LState) int { | |||
now := float64(time.Now().UnixNano()) / float64(time.Second) | |||
L.Push(lua.LNumber(now)) | |||
return 1 | |||
} | |||
func UnixNano(L *lua.LState) int { | |||
L.Push(lua.LNumber(time.Now().UnixNano())) | |||
return 1 | |||
} | |||
func Sleep(L *lua.LState) int { | |||
val := L.CheckNumber(1) | |||
time.Sleep(time.Duration(val) * time.Second) | |||
return 0 | |||
} | |||
func Parse(L *lua.LState) int { | |||
layout, value := L.CheckString(2), L.CheckString(1) | |||
result, err := time.Parse(layout, value) | |||
if err != nil { | |||
L.Push(lua.LNil) | |||
L.Push(lua.LString(err.Error())) | |||
return 2 | |||
} | |||
resultFloat := float64(result.UTC().UnixNano()) / float64(time.Second) | |||
L.Push(lua.LNumber(resultFloat)) | |||
return 1 | |||
} | |||
func Format(L *lua.LState) int { | |||
tt := float64(L.CheckNumber(1)) | |||
sec := int64(tt) | |||
nsec := int64((tt - float64(sec)) * 1000000000) | |||
result := time.Unix(sec, nsec) | |||
layout := "Mon Jan 2 15:04:05 -0700 MST 2006" | |||
if L.GetTop() > 1 { | |||
layout = L.CheckString(2) | |||
} | |||
if L.GetTop() < 3 { | |||
L.Push(lua.LString(result.Format(layout))) | |||
return 1 | |||
} | |||
location := L.CheckString(3) | |||
loc, err := time.LoadLocation(location) | |||
if err != nil { | |||
L.Push(lua.LNil) | |||
L.Push(lua.LString(err.Error())) | |||
return 2 | |||
} | |||
result = result.In(loc) | |||
L.Push(lua.LString(result.Format(layout))) | |||
return 1 | |||
} |
@ -0,0 +1,15 @@ | |||
package time | |||
import ( | |||
"testing" | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func TestApi(t *testing.T) { | |||
state := lua.NewState() | |||
PreLoadGo(state) | |||
if err := state.DoFile("../testScript/test_time_api.lua"); err != nil { | |||
t.Fatalf("execute test: %s\n", err.Error()) | |||
} | |||
} |
@ -0,0 +1,24 @@ | |||
package time | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
) | |||
func PreLoadGo(L *lua.LState) { | |||
L.PreloadModule("time", Loader) | |||
} | |||
func Loader(L *lua.LState) int { | |||
t := L.NewTable() | |||
L.SetFuncs(t, api) | |||
L.Push(t) | |||
return 1 | |||
} | |||
var api = map[string]lua.LGFunction{ | |||
"unix": Unix, | |||
"unix_nano": UnixNano, | |||
"sleep": Sleep, | |||
"parse": Parse, | |||
"format": Format, | |||
} |
@ -0,0 +1,199 @@ | |||
package luaInGo | |||
// import ( | |||
// "context" | |||
// "sync" | |||
// "sync/atomic" | |||
// "time" | |||
// | |||
// log "github.com/iglev/ilog" | |||
// ) | |||
// | |||
// type hotfixMgr interface { | |||
// reg(file string) | |||
// check(L *LState) *hotfixList | |||
// } | |||
// | |||
// func newHotfixMgr(ctx context.Context, needCoro bool, hotfixTime int64) hotfixMgr { | |||
// var ht hotfixMgr | |||
// if needCoro { | |||
// htco := &hotfixMgrCoro{ | |||
// ctx: ctx, | |||
// ch: make(chan *hotfixList, 16), | |||
// hotfixTime: hotfixTime, | |||
// } | |||
// go htco.loop() | |||
// ht = htco | |||
// } else { | |||
// ht = &hotfixMgrLocal{ | |||
// mp: make(map[string]int64), | |||
// lasttime: time.Now().Unix(), | |||
// hotfixTime: hotfixTime, | |||
// } | |||
// } | |||
// return ht | |||
// } | |||
// | |||
// type hotfixList struct { | |||
// files []string | |||
// } | |||
// | |||
// func hotfixDoFile(L *LState, ht hotfixMgr, up *hotfixList) { | |||
// size := len(up.files) | |||
// for i := 0; i < size; i++ { | |||
// err := L.L().DoFile(up.files[i]) | |||
// if err != nil { | |||
// log.Error("DoFile fail, file=%v err=%v", up.files[i], err) | |||
// } else { | |||
// log.Info("reload file=%v success", up.files[i]) | |||
// } | |||
// } | |||
// } | |||
// | |||
// ////////////////////////////////////////////////////////////////// | |||
// // hotfixMgrLocal | |||
// | |||
// type hotfixMgrLocal struct { | |||
// mp map[string]int64 | |||
// lasttime int64 | |||
// hotfixTime int64 | |||
// } | |||
// | |||
// func (ht *hotfixMgrLocal) reg(file string) { | |||
// mt, err := getFileModtime(file) | |||
// if err != nil { | |||
// return | |||
// } | |||
// ht.mp[file] = mt | |||
// } | |||
// | |||
// func (ht *hotfixMgrLocal) check(L *LState) *hotfixList { | |||
// curr := time.Now().Unix() | |||
// lasttime := atomic.LoadInt64(&ht.lasttime) | |||
// if curr < (lasttime + ht.hotfixTime) { | |||
// return nil | |||
// } | |||
// atomic.StoreInt64(&ht.lasttime, curr) | |||
// up := ht.getHotfixList() | |||
// if up != nil { | |||
// hotfixDoFile(L, ht, up) | |||
// } | |||
// return up | |||
// } | |||
// | |||
// func (ht *hotfixMgrLocal) getHotfixList() *hotfixList { | |||
// size := len(ht.mp) | |||
// if size <= 0 { | |||
// return nil | |||
// } | |||
// up := &hotfixList{ | |||
// files: make([]string, 0, size), | |||
// } | |||
// tmp := make(map[string]int64) | |||
// for k, v := range ht.mp { | |||
// mt, err := getFileModtime(k) | |||
// if err != nil { | |||
// log.Error("getFileModtime fail, file=%v err=%v", k, err) | |||
// continue | |||
// } | |||
// if v != mt { | |||
// up.files = append(up.files, k) | |||
// tmp[k] = mt | |||
// } | |||
// } | |||
// for k, v := range tmp { | |||
// ht.mp[k] = v | |||
// } | |||
// return up | |||
// } | |||
// | |||
// ////////////////////////////////////////////////////////////////// | |||
// // hotfixMgrCoro | |||
// | |||
// type hotfixMgrCoro struct { | |||
// ctx context.Context | |||
// mp sync.Map | |||
// ch chan *hotfixList | |||
// hotfixTime int64 | |||
// } | |||
// | |||
// func (ht *hotfixMgrCoro) reg(file string) { | |||
// mt, err := getFileModtime(file) | |||
// if err != nil { | |||
// return | |||
// } | |||
// ht.mp.Store(file, mt) | |||
// } | |||
// | |||
// func (ht *hotfixMgrCoro) check(L *LState) *hotfixList { | |||
// up := ht.getHotfixList() | |||
// if up != nil { | |||
// hotfixDoFile(L, ht, up) | |||
// } | |||
// return up | |||
// } | |||
// | |||
// func (ht *hotfixMgrCoro) getHotfixList() *hotfixList { | |||
// select { | |||
// case up := <-ht.ch: | |||
// return up | |||
// default: | |||
// return nil | |||
// } | |||
// } | |||
// | |||
// func (ht *hotfixMgrCoro) loop() { | |||
// timer := time.NewTimer(time.Duration(ht.hotfixTime) * time.Second) | |||
// defer timer.Stop() | |||
// Loop: | |||
// for { | |||
// select { | |||
// case <-timer.C: | |||
// ht.loopCheck() | |||
// timer.Reset(time.Duration(ht.hotfixTime) * time.Second) | |||
// case <-ht.ctx.Done(): | |||
// break Loop | |||
// } | |||
// } | |||
// } | |||
// | |||
// func (ht *hotfixMgrCoro) loopCheck() { | |||
// var up *hotfixList | |||
// mp := make(map[string]int64) | |||
// ht.mp.Range(func(k, v interface{}) bool { | |||
// file, ok := k.(string) | |||
// if !ok { | |||
// return false | |||
// } | |||
// oldmt, mtOK := v.(int64) | |||
// if !mtOK { | |||
// return false | |||
// } | |||
// newmt, err := getFileModtime(file) | |||
// if err != nil { | |||
// log.Error("getFileModtime fail, file=%v err=%v", file, err) | |||
// return false | |||
// } | |||
// if newmt != oldmt { | |||
// mp[file] = newmt | |||
// } | |||
// return true | |||
// }) | |||
// size := len(mp) | |||
// if size > 0 { | |||
// up = &hotfixList{ | |||
// files: make([]string, 0, size), | |||
// } | |||
// for k, v := range mp { | |||
// ht.mp.Store(k, v) | |||
// up.files = append(up.files, k) | |||
// } | |||
// select { | |||
// case ht.ch <- up: | |||
// return | |||
// default: | |||
// log.Error("hotfix send to channel fail, up=%v", up) | |||
// } | |||
// } | |||
// } | |||
// |
@ -0,0 +1,136 @@ | |||
require ("math") | |||
module('bit', package.seeall) -- 实现按位运算 | |||
--默认按32位 | |||
local __bitNum = 32 | |||
--设置位数 | |||
function setBitNum(bitNum) | |||
__bitNum = bitNum | |||
end | |||
--按位同或 | |||
function bxnor(int1, int2) | |||
return __operaByBit(__bitxnor, int1, int2) | |||
end | |||
--按位异或 | |||
function bxor(int1, int2) | |||
return __operaByBit(__bitxor, int1, int2) | |||
end | |||
--按位与 | |||
function band(int1, int2) | |||
return __operaByBit(__bitand, int1, int2) | |||
end | |||
--按位或 | |||
function bor(int1, int2) | |||
return __operaByBit(__bitor, int1, int2) | |||
end | |||
--按位非 | |||
function bnot(integer) | |||
return __operaByBit(__bitnot, integer) | |||
end | |||
--按位操作 | |||
function __operaByBit(bitFunc, ...) | |||
local bDataLst = {} | |||
for i = 1, select("#", ...) do | |||
local bData = itob(select(i, ...)) | |||
table.insert(bDataLst, bData) | |||
end | |||
for _, bData in ipairs(bDataLst) do | |||
for i = #bData + 1, __bitNum do | |||
table.insert(bData, 1, 0) | |||
end | |||
end | |||
local resData = {} | |||
for i = 1, __bitNum do | |||
local args = {} | |||
for _, bData in ipairs(bDataLst) do | |||
table.insert(args, bData[i]) | |||
end | |||
table.insert(resData, bitFunc(unpack(args))) | |||
end | |||
return btoi(resData) | |||
end | |||
--按位同或 | |||
function __bitxnor(bit1, bit2) | |||
return (bit1 == bit2) and 1 or 0 | |||
end | |||
--按位异或 | |||
function __bitxor(bit1, bit2) | |||
return (bit1 == bit2) and 0 or 1 | |||
end | |||
--按位与 | |||
function __bitand(bit1, bit2) | |||
return (bit1 == 1 and bit2 == 1) and 1 or 0 | |||
end | |||
--按位或 | |||
function __bitor(bit1, bit2) | |||
return (bit1 == 1 or bit2 == 1) and 1 or 0 | |||
end | |||
--按位非 | |||
function __bitnot(bit) | |||
return 1 - bit | |||
end | |||
--2进制转换成10进制 | |||
function btoi(bData) | |||
return __ntoi(bData, 2) | |||
end | |||
--10进制转换成2进制 | |||
function itob(integer) | |||
return __iton(integer, 2) | |||
end | |||
--10进制转换成N进制 | |||
function __iton(integer, num) | |||
assert(type(integer) == "number") | |||
if integer == 0 then | |||
return {0} | |||
end | |||
local bNeg = integer < 0 | |||
local ci = math.abs(integer) | |||
local nData = {} | |||
while ci > 0 do | |||
table.insert(nData, 1, ci % num) | |||
ci = math.floor(ci / num) | |||
end | |||
if bNeg then | |||
for i = #nData + 1, __bitNum do | |||
table.insert(nData, 1, num - 1) | |||
end | |||
end | |||
return nData | |||
end | |||
--N进制转换成10进制 | |||
function __ntoi(nData, num) | |||
assert(type(nData) == "table") | |||
local integer = 0 | |||
for i, data in ipairs(nData) do | |||
integer = integer + data * math.pow(num, #nData - i) | |||
end | |||
return integer | |||
end | |||
@ -0,0 +1,80 @@ | |||
function GetClassName(name) | |||
for k,v in pairs(_G) do | |||
if name==v then | |||
return k | |||
end | |||
end | |||
end | |||
function CreateClass(name,basename) | |||
if _G[name] ~= nil then | |||
unilight.error("CreateClass被意外全局初始化,这里强制重置成类:"..name) | |||
return nil | |||
end | |||
_G[name] = {} | |||
local class = _G[name] | |||
if basename then | |||
local baseclass = _G[basename] | |||
if baseclass then | |||
for k,v in pairs(baseclass) do | |||
class[k] = v | |||
end | |||
else | |||
unilight.error("CreateClass error:" .. tostring(name) .. ":" .. tostring(basename)) | |||
end | |||
end | |||
class.__classname = name | |||
function class:New(initclass) | |||
local new = initclass or {} | |||
setmetatable(new, { __index = self}) | |||
return new | |||
end | |||
function class:SetClassName(cname) | |||
self.__classname = cname or self.__classname | |||
end | |||
function class:GetLogPrefix() | |||
local id = nil | |||
local name = "" | |||
if self.GetId then | |||
id = self:GetId() | |||
elseif self.id then | |||
id = self.id | |||
elseif self.Id then | |||
id = self.Id | |||
elseif self.tempid then | |||
id = self.tempid | |||
elseif self.Tempid then | |||
id = self.Tempid | |||
end | |||
if self.GetName then | |||
name = self:GetName() | |||
elseif self.name then | |||
name = self.name | |||
elseif self.Name then | |||
name = self.Name | |||
end | |||
local id = id or "" | |||
local name = name or "" | |||
return self.__classname .. "[" .. id .."," ..name.. "] " | |||
end | |||
function class:Debug(...) | |||
unilight.debug(self:GetLogPrefix() .. unpack(arg)) | |||
end | |||
function class:Info(...) | |||
unilight.info(self:GetLogPrefix() .. unpack(arg)) | |||
end | |||
function class:Warn(...) | |||
unilight.warn(self:GetLogPrefix() .. unpack(arg)) | |||
end | |||
function class:Error(...) | |||
unilight.error(self:GetLogPrefix() .. unpack(arg)) | |||
end | |||
function class:Stack(...) | |||
unilight.stack(self:GetLogPrefix() .. unpack(arg)) | |||
end | |||
return class | |||
end | |||
--Class = CreateClass("Class") | |||
--new = Class:New() | |||
--new:Debug("whj") |
@ -0,0 +1,295 @@ | |||
-- 通用lua扩充函数,与任何游戏逻辑无关 | |||
-- from http://snippets.luacode.org/?p=snippets/String_to_Hex_String_68 | |||
string.tohex = function(str, spacer) | |||
return string.gsub(str,"(.)", function (c) return string.format("%02X%s", string.byte(c), spacer or "") end) | |||
end | |||
string.trim = function(str) | |||
return string.gsub(str, "^%s*(.-)%s*$", "%1") | |||
end | |||
string.trimbegin = function(str) | |||
return string.gsub(str, "^%s*(.-)$", "%1") | |||
end | |||
string.trimend = function(str) | |||
return string.gsub(str, "^(.-)%s*$", "%1") | |||
end | |||
string.padleft = function(str, totalWidth, paddingChar) | |||
local len = #str | |||
if len >= totalWidth then | |||
return str | |||
else | |||
paddingChar = paddingChar or ' ' | |||
assert(#paddingChar == 1) | |||
return string.rep(paddingChar, totalWidth - len) .. str | |||
end | |||
end | |||
string.padright = function(str, totalWidth, paddingChar) | |||
local len = #str | |||
if len >= totalWidth then | |||
return str | |||
else | |||
paddingChar = paddingChar or ' ' | |||
assert(#paddingChar == 1) | |||
return str .. string.rep(paddingChar, totalWidth - len) | |||
end | |||
end | |||
string.split = function(szFullString, szSeparator) | |||
local FindStartIndex = 1 | |||
local SplitArray = {} | |||
while true do | |||
local FindLastIndex = string.find(szFullString, szSeparator, FindStartIndex, true) | |||
if not FindLastIndex then | |||
table.insert(SplitArray, string.sub(szFullString, FindStartIndex, string.len(szFullString))) | |||
break | |||
end | |||
table.insert(SplitArray, string.sub(szFullString, FindStartIndex, FindLastIndex-1)) | |||
FindStartIndex = FindLastIndex + string.len(szSeparator) | |||
end | |||
return SplitArray | |||
end | |||
string.isNilOrEmpty = function(str) | |||
if str == nil then | |||
return true, nil | |||
end | |||
if type(str) ~= "string" then | |||
return true, nil | |||
end | |||
local fstr = string.match(str,"%s*(.-)%s*$") | |||
local ret = fstr == "" | |||
if ret == true then | |||
str = nil | |||
end | |||
return ret, fstr | |||
end | |||
table.find = function(this, value) | |||
for k,v in pairs(this) do | |||
if v == value then return k end | |||
end | |||
end | |||
table.omit = function(tbl) | |||
for k,v in pairs(tbl) do | |||
local typ = type(v) | |||
if typ == "table" then | |||
v = table.omit(v) | |||
if v == nil or next(v) == nil then | |||
tbl[k] = nil | |||
end | |||
elseif (typ == "string" and v == "") or (typ == "number" and v == 0) then | |||
tbl[k] = nil | |||
end | |||
end | |||
return tbl | |||
end | |||
table.tostring = function(data, _indent) | |||
local visited = {} | |||
local function dump(data, prefix) | |||
local str = tostring(data) | |||
if table.find(visited, data) ~= nil then return str end | |||
table.insert(visited, data) | |||
local prefix_next = prefix .. " " | |||
str = str .. "\n" .. prefix .. "{" | |||
for k,v in pairs(data) do | |||
if type(k) == "number" then | |||
str = str .. "\n" .. prefix_next .. "[" .. tostring(k) .. "] = " | |||
else | |||
str = str .. "\n" .. prefix_next .. tostring(k) .. " = " | |||
end | |||
if type(v) == "table" then | |||
str = str .. dump(v, prefix_next) | |||
elseif type(v) == "string" then | |||
str = str .. '"' .. v .. '"' | |||
else | |||
str = str .. tostring(v) | |||
end | |||
end | |||
str = str .. "\n" .. prefix .. "}" | |||
return str | |||
end | |||
return dump(data, _indent or "") | |||
end | |||
table.merge = function(base, delta) | |||
if type(delta) ~= "table" then return end | |||
for k,v in pairs(delta) do | |||
base[k] = v | |||
end | |||
end | |||
table.extend = function(base, delta) | |||
if type(delta) ~= "table" then return end | |||
for i,v in ipairs(delta) do | |||
table.insert(base, v) | |||
end | |||
end | |||
table.len = function(tbl) | |||
if type(tbl) ~= "table" then return 0 end | |||
local n = 0 | |||
for k,v in pairs(tbl) do n = n + 1 end | |||
return n | |||
end | |||
table.empty = function(tbl) | |||
if tbl == nil then return true end | |||
assert(type(tbl) == "table") | |||
return next(tbl) == nil | |||
--if #tbl > 0 then return false end | |||
--for k,v in pairs(tbl) do return false end | |||
--return true | |||
end | |||
-- http://snippets.luacode.org/?p=snippets/Deep_copy_of_a_Lua_Table_2 | |||
table.clone = function(t,deepnum) | |||
if type(t) ~= 'table' then return t end | |||
local mt = getmetatable(t) | |||
local res = {} | |||
if deepnum and deepnum > 0 then | |||
deepnum = deepnum - 1 | |||
end | |||
for k,v in pairs(t) do | |||
if type(v) == 'table' then | |||
if not deepnum or deepnum > 0 then | |||
v = table.clone(v, deepnum) | |||
end | |||
end | |||
res[k] = v | |||
end | |||
setmetatable(res,mt) | |||
return res | |||
end | |||
-- http://snippets.luacode.org/?p=snippets/Table_Slice_116 | |||
table.slice = function(values,i1,i2) | |||
local res = {} | |||
local n = #values | |||
i1 = i1 or 1 | |||
i2 = i2 or n | |||
if i2 < 0 then | |||
i2 = n + i2 + 1 | |||
elseif i2 > n then | |||
i2 = n | |||
end | |||
if i1 < 1 or i1 > n then | |||
return {} | |||
end | |||
local k = 1 | |||
for i = i1,i2 do | |||
res[k] = values[i] | |||
k = k + 1 | |||
end | |||
return res | |||
end | |||
table.reverse = function(tab) | |||
local size = #tab | |||
local newTable = {} | |||
for i,v in ipairs(tab) do | |||
newTable[size+1-i] = v | |||
end | |||
return newTable | |||
end | |||
table.reset = function(t) | |||
for k,v in pairs(t) do | |||
t[k] = nil | |||
end | |||
return t | |||
end | |||
-- math.random({0.7, 0.1, 0.2}, {'A', 'B', 'C'}) | |||
math.random = function(m, n) | |||
if type(m) == "table" and #m == #n then | |||
-- 标准化概率表 | |||
local sum = 0 | |||
for _,v in ipairs(m) do sum = sum + v end | |||
local sm = {} | |||
for k,v in ipairs(m) do sm[k] = v / sum end | |||
-- 得到下标 | |||
local r = go.rand.Random() | |||
for k,v in ipairs(sm) do | |||
if r <= v then return n[k] | |||
else r = r - v end | |||
end | |||
assert(false) | |||
end | |||
if m == nil then return go.rand.Random() end | |||
local _random = function(m, n) | |||
m, n = math.min(m, n), math.max(m, n) | |||
local mi, mf = math.modf(m) | |||
local ni, nf = math.modf(n) | |||
if mf == 0 and nf == 0 then | |||
return go.rand.RandBetween(m, n) | |||
else | |||
return m + go.rand.Random() * (n - m) | |||
end | |||
end | |||
if n == nil then return _random(1, m) end | |||
return _random(m, n) | |||
end | |||
-- http://www.cplusplus.com/reference/algorithm/random_shuffle/ | |||
-- http://stackoverflow.com/questions/17119804/lua-array-shuffle-not-working | |||
math.shuffle = function(array) | |||
local counter = #array | |||
while counter > 1 do | |||
local index = math.random(counter) | |||
array[index], array[counter] = array[counter], array[index] | |||
counter = counter - 1 | |||
end | |||
return array | |||
end | |||
--按table的key排序遍历table e.g. for k, v in pairsByKeys(tab, function(v1,v2) return v1 > v2 end) do print(k, v) end | |||
function pairsByKeys(t, sortfunc) | |||
local kt = {} | |||
local len = 0 | |||
for k in pairs(t) do | |||
len = len + 1 | |||
kt[len] = k | |||
end | |||
table.sort(kt, sortfunc) | |||
local i = 0 | |||
return function() | |||
i = i + 1 | |||
return kt[i], t[kt[i]] | |||
end | |||
end | |||
--计算utf8字符串的长度 from quickcocos | |||
function string.utf8len(input) | |||
local len = string.len(input) | |||
local left = len | |||
local cnt = 0 | |||
local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc} | |||
while left ~= 0 do | |||
local tmp = string.byte(input, -left) | |||
local i = #arr | |||
while arr[i] do | |||
if tmp >= arr[i] then | |||
left = left - i | |||
break | |||
end | |||
i = i - 1 | |||
end | |||
cnt = cnt + 1 | |||
end | |||
return cnt | |||
end | |||
--检查一个文件是否存在 | |||
function file_exists(path) | |||
local file = io.open(path, "rb") | |||
if file then file:close() end | |||
return file ~= nil | |||
end |
@ -0,0 +1,37 @@ | |||
module('random', package.seeall) | |||
--添加的随机概率函数--------- | |||
----小数点概率--- | |||
function selectByPoint(value) | |||
if value == nil or value <= 0 then | |||
return false | |||
end | |||
local value = math.ceil(1 / value) | |||
return selectByRegion(1, value) | |||
end | |||
----百分比概率--- | |||
function selectByPercent(value) | |||
if value < 1 then | |||
return false | |||
end | |||
return selectByRegion(value, 100) | |||
end | |||
----万分比概率--- | |||
function selectByTenTh(value) | |||
if value < 1 then | |||
return false | |||
end | |||
return selectByRegion(value, 10000) | |||
end | |||
function selectByRegion(down, up) | |||
if down >= up then | |||
return true | |||
end | |||
local random = math.random(1, up) | |||
return random <= down | |||
end |
@ -0,0 +1,42 @@ | |||
unilight = unilight or {} | |||
os.time = go.time.luatime() | |||
os.msectime = go.time.Msec | |||
os.nsectime = go.time.Nsec | |||
-- log -- | |||
unilight.debug = function(...) | |||
local arg = {...} | |||
go.logging.debug(arg[1], arg[2] or {}) | |||
end | |||
unilight.info = function(...) | |||
local arg = {...} | |||
go.logging.info(arg[1], arg[2] or {}) | |||
end | |||
unilight.warn = function(...) | |||
print("unilight-warn:" .. tostring(...)) | |||
local arg = {...} | |||
go.logging.warning(arg[1], arg[2] or {}) | |||
end | |||
unilight.error = function(...) | |||
local arg = {...} | |||
if next(arg) == nil then | |||
unilight.error(debug.traceback()) | |||
end | |||
go.logging.error(arg[1], arg[2] or {}) | |||
end | |||
unilight.stack = function(...) | |||
local arg = {...} | |||
print("unilight-stack:" .. tostring(...)) | |||
end | |||
unilight.tablefiles = function() | |||
return luar.slice2table(go.getLuaFiles(go.tablePath)) | |||
end | |||
unilight.scriptfiles = function() | |||
return luar.slice2table(go.getLuaFiles(go.scriptPath)) | |||
end |
@ -0,0 +1,21 @@ | |||
uniregexp= uniregexp or {} | |||
--[[ | |||
exp: | |||
uniregexp.match("foo.*","seafood") => true nil | |||
uniregexp.match("bar.*","seafood") => false nil | |||
uniregexp.match("a(b","seafood") => false error parsing regexp: missing closing ): `a(b` | |||
--]] | |||
uniregexp.match = function(pattern, s) | |||
return go.uniregexp.Match(pattern, s) | |||
end | |||
--[[ | |||
exp: | |||
quotemeta(`[foo]`) => `\[foo\]` | |||
--]] | |||
uniregexp.quotemeta = function(s) | |||
return go.uniregexp.QuoteMeta(s) | |||
end | |||
-- 其余api可以调用go.uniregexp.***** 参考go语言 regexp.Regexp类方法 |
@ -0,0 +1,137 @@ | |||
CreateClass("UniTimerClass") | |||
CreateClass("UniEventClass") | |||
function NewUniTimerClass(callback, msec, ...) | |||
local timer = { | |||
nextmsec=unitimer.now, | |||
callback = callback, | |||
tick = msec, | |||
params = arg, | |||
} | |||
UniTimerClass:New(timer) | |||
return timer | |||
end | |||
function NewUniTimerRandomClass(callback, msec, ...) | |||
local timer = { | |||
nextmsec=unitimer.now+math.random(msec/2,msec), | |||
callback = callback, | |||
tick = msec, | |||
params = arg, | |||
} | |||
UniTimerClass:New(timer) | |||
return timer | |||
end | |||
function NewUniEventClass(callback, msec,maxtimes, ...) | |||
local event = { | |||
nextmsec=unitimer.now+msec, | |||
callback = callback, | |||
tick = msec, | |||
maxtimes = maxtimes, | |||
params = arg, | |||
} | |||
UniEventClass:New(event) | |||
return event | |||
end | |||
function UniTimerClass:GetId() | |||
return self.tick | |||
end | |||
function UniTimerClass:GetName() | |||
return self.tick | |||
end | |||
function UniTimerClass:Stop() | |||
self.stop = true | |||
unitimer.removetimer(self) | |||
end | |||
function UniTimerClass:Check(now,force) | |||
if self.nextmsec <= now or force then | |||
--unilight.error("UniEventClass:"..unpack(self.params)) | |||
self.nextmsec = now + self.tick --如果callback脚本报错,会悲剧,WHJ,似乎没人用,先提前试试 | |||
self.callback(unpack(self.params)) | |||
return true | |||
end | |||
--duaration=0 | |||
--first=true | |||
--pause=false | |||
--stop=false | |||
return false | |||
end | |||
function UniEventClass:GetId() | |||
return self.tick | |||
end | |||
function UniEventClass:GetName() | |||
return self.maxtimes | |||
end | |||
function UniEventClass:Check(now,force) | |||
--if (self.nextmsec <= now or force) and self.tick > 0 then | |||
if (self.maxtimes > 0 and self.nextmsec <= now) or force then | |||
self.nextmsec = now + self.tick --如果callback脚本报错,会悲剧,WHJ,似乎没人用,先提前试试 | |||
self.maxtimes = self.maxtimes - 1 --计数可以提前,时间不能提前,有可能逻辑里要用时间,提前的目的是防止Check报错后就悲剧 | |||
self.callback(unpack(self.params)) | |||
return true | |||
end | |||
return false | |||
end | |||
function UniEventClass:Stop() | |||
unitimer.removeevent(self) | |||
end | |||
unitimer={ | |||
timermap={}, | |||
eventmap={}, | |||
} | |||
function unitimer.init(msec) --最小精度的定时器 | |||
unitimer.now = go.time.Msec() | |||
if unitimer.ticktimer ~= nil then | |||
unilight.error("unitimer.init已经初始化过了:"..unitimer.tickmsec) | |||
return false | |||
end | |||
unitimer.tickmsec = msec --保存最小精度 | |||
unitimer.ticktimer = unilight.addtimermsec("unitimer.loop", msec) | |||
return true | |||
end | |||
function unitimer.loop() | |||
local timer = unitimer | |||
timer.now = go.time.Msec() | |||
for k,v in pairs(timer.timermap) do | |||
if v:Check(timer.now) == true then | |||
if v.stop == true then | |||
timer.removetimer(v) | |||
end | |||
end | |||
end | |||
for k,v in pairs(timer.eventmap) do | |||
if v:Check(timer.now) == true then | |||
if v.maxtimes <= 0 then | |||
--v:Debug("事件结束") | |||
v:Stop() | |||
end | |||
end | |||
end | |||
end | |||
function unitimer.addtimermsec(callback, msec, ...) | |||
local timer = NewUniTimerClass(callback, msec, ...) | |||
--timer:Debug("unitimer.addtimermsec:") | |||
unitimer.timermap[timer]=timer | |||
return timer | |||
end | |||
function unitimer.addtimer(callback, msec, ...) | |||
return unitimer.addtimermsec(callback, msec*1000, ...) | |||
end | |||
function unitimer.removetimer(timer) | |||
--timer:Debug("unitimer.removetimer:") | |||
unitimer.timermap[timer] = nil | |||
end | |||
function unitimer.addevent(callback, msec,maxtimes, ...) | |||
return unitimer.addeventmsec(callback, msec*1000,maxtimes, ...) | |||
end | |||
function unitimer.addeventmsec(callback, msec,maxtimes, ...) | |||
maxtime = maxtimes or 1 | |||
local event = NewUniEventClass(callback, msec,maxtimes, ...) | |||
--event:Debug("设置事件:"..msec) | |||
unitimer.eventmap[event]=event | |||
return event | |||
end | |||
function unitimer.removeevent(event) | |||
unitimer.eventmap[event] = nil | |||
end |
@ -0,0 +1,118 @@ | |||
local pattern = '[%z\1-\127\194-\244][\128-\191]*' | |||
-- helper function | |||
local posrelat = | |||
function (pos, len) | |||
if pos < 0 then | |||
pos = len + pos + 1 | |||
end | |||
return pos | |||
end | |||
utf8 = {} | |||
-- maps f over s's utf8 characters f can accept args: (visual_index, utf8_character, byte_index) | |||
utf8.map = | |||
function (s, f, no_subs) | |||
local i = 0 | |||
if no_subs then | |||
for b, e in s:gmatch('()' .. pattern .. '()') do | |||
i = i + 1 | |||
local c = e - b | |||
f(i, c, b) | |||
end | |||
else | |||
for b, c in s:gmatch('()(' .. pattern .. ')') do | |||
i = i + 1 | |||
f(i, c, b) | |||
end | |||
end | |||
end | |||
-- generator for the above -- to iterate over all utf8 chars | |||
utf8.chars = | |||
function (s, no_subs) | |||
return coroutine.wrap(function () return utf8.map(s, coroutine.yield, no_subs) end) | |||
end | |||
-- returns the number of characters in a UTF-8 string | |||
utf8.len = | |||
function (s) | |||
-- count the number of non-continuing bytes | |||
return select(2, s:gsub('[^\128-\193]', '')) | |||
end | |||
utf8.GetMaxLenString = | |||
function (s, maxlen, symbol) | |||
-- s:待裁剪字符串,maxlen:最大长度,symbol:裁剪后补全符号 | |||
symbol = symbol or "" | |||
local len = utf8.len(s) | |||
local dstString = s | |||
-- 超长,裁剪,加symbol | |||
if len > maxlen then | |||
dstString = utf8.sub(s, 1, maxlen) | |||
dstString = dstString..symbol | |||
end | |||
return dstString | |||
end | |||
-- replace all utf8 chars with mapping | |||
utf8.replace = | |||
function (s, map) | |||
return s:gsub(pattern, map) | |||
end | |||
-- reverse a utf8 string | |||
utf8.reverse = | |||
function (s) | |||
-- reverse the individual greater-than-single-byte characters | |||
s = s:gsub(pattern, function (c) return #c > 1 and c:reverse() end) | |||
return s:reverse() | |||
end | |||
-- strip non-ascii characters from a utf8 string | |||
utf8.strip = | |||
function (s) | |||
return s:gsub(pattern, function (c) return #c > 1 and '' end) | |||
end | |||
-- like string.sub() but i, j are utf8 strings | |||
-- a utf8-safe string.sub() | |||
utf8.sub = | |||
function (s, i, j) | |||
local l = utf8.len(s) | |||
i = posrelat(i, l) | |||
j = j and posrelat(j, l) or l | |||
if i < 1 then i = 1 end | |||
if j > l then j = l end | |||
if i > j then return '' end | |||
local diff = j - i | |||
local iter = utf8.chars(s, true) | |||
-- advance up to i | |||
for _ = 1, i - 1 do iter() end | |||
local c, b = select(2, iter()) | |||
-- i and j are the same, single-charaacter sub | |||
if diff == 0 then | |||
return string.sub(s, b, b + c - 1) | |||
end | |||
i = b | |||
-- advance up to j | |||
for _ = 1, diff - 1 do iter() end | |||
c, b = select(2, iter()) | |||
return string.sub(s, i, b + c - 1) | |||
end | |||
@ -0,0 +1,76 @@ | |||
package luaInGo | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
"strings" | |||
"sync" | |||
) | |||
type lStatePool struct { | |||
m sync.Mutex | |||
saved []*lua.LState | |||
} | |||
// Get 从池中取出一个LState,若池中没有,则新增一个 | |||
func (pl *lStatePool) Get() *lua.LState { | |||
pl.m.Lock() | |||
defer pl.m.Unlock() | |||
n := len(pl.saved) | |||
if n == 0 { | |||
return pl.New() | |||
} | |||
x := pl.saved[n-1] | |||
pl.saved = pl.saved[0 : n-1] | |||
return x | |||
} | |||
// Put 用完LState后放回池中 | |||
func (pl *lStatePool) Put(L *lua.LState) { | |||
pl.m.Lock() | |||
defer pl.m.Unlock() | |||
if len(pl.saved) > NaxPoolSize { | |||
L.Close() | |||
} else { | |||
// 放回的时候 清理一下 堆栈 确认数据正常 | |||
L.SetTop(0) | |||
pl.saved = append(pl.saved, L) | |||
} | |||
} | |||
func (pl *lStatePool) ShutDown() { | |||
for _, L := range pl.saved { | |||
L.Close() | |||
} | |||
} | |||
func (pl *lStatePool) New() *lua.LState { | |||
L := lua.NewState() | |||
//提供全局函数给lua | |||
PreLoadGo(L) | |||
//加载go提供元表给lua | |||
// golua.RegisterPersonType(L) | |||
// 添加lua脚本自动搜索路径 | |||
// Tamper package.path according to configuration... | |||
t := L.GetGlobal("package").(*lua.LTable) | |||
// Get "path" from package table | |||
lPath := lua.LString("path") | |||
s := L.RawGet(t, lPath).(lua.LString).String() | |||
// Create list of elements to join for new package path | |||
elems := []string{s} | |||
elems = append(elems, "./luaScript/?.lua") | |||
// Set new package.path | |||
L.RawSet(t, lPath, lua.LString(strings.Join(elems, ";"))) | |||
//加载lua脚本 仅仅加载入口函数模块的lua | |||
if err := L.DoFile("./luaScript/main.lua"); err != nil { | |||
println("load the main lua files error") | |||
panic(err) | |||
} | |||
return L | |||
} |
@ -0,0 +1,21 @@ | |||
package luaInGo | |||
import ( | |||
lua "github.com/yuin/gopher-lua" | |||
"luaInGo/goApis" | |||
"luaInGo/goApis/crypto" | |||
"luaInGo/goApis/json" | |||
"luaInGo/goApis/strings" | |||
"luaInGo/goApis/time" | |||
) | |||
// 这里封装一个函数 统一load go中提供给lua调用的函数 | |||
func PreLoadGo(L *lua.LState) { | |||
// 这里再调用一些子模块的LoadGo()函数 | |||
time.PreLoadGo(L) | |||
strings.PreLoadGo(L) | |||
crypto.PreLoadGo(L) | |||
json.PreloadGo(L) | |||
goApis.PreLoadLibs(L) | |||
} |